0

this may be very fundamental C# question as I only study C# myself there are things that I do not have the logic to start.

I have a class CustomerSite with string Customer {get;set} and string Site {get;set;}

I create a list List<CustomerSite> listCustomerSite= new List<CustomerSite>();

Assume, I have a list with the following data

SAMSUNG CHINA
SAMSUNG AMERICA
SAMSUNG AFRICA
LG  CHINA
APPLE AMERICA
APPLE CHINA

I would like to have 1 concatenated string

string Result = "APPLE (AMERICA, CHINA), LG (CHINA), SAMSUNG (AFRICA, AMERICA, CHINA)"

How could I do that?

My idea is to use a dictionary to keep a list of distinct Customers and adding the site to the string but I still have no clue how to deal with sorting (AFRICA --> AMERICA --> CHINA)

Dictionary<string, int> dictCustomer = new Dictionary<string, int>();
foreach (var i in listCustomerSite)
{
    if (!dictCustomer.ContainsKey(i.Customer))
    {
        dictCustomer.Add(i.Customer, 0);
        Result = Result + "," + "i.Customer" + "( i.Site) ";
    }
    else
    {
        Result.Replace(")", "," + i.Site + ")");
    }
}
1
  • maybe offtopic for your question but keep in mind that a dictionary doesn't guarantee the insertion order. Commented Aug 10, 2018 at 16:45

4 Answers 4

7

You can utilize LINQ and String.Join to group your collection by customer, convert each grouping to a formatted string with sorted comma-separated sites, and then combine them to a single string:

var customersWithLocations = listCustomerSite
    .GroupBy(cs => cs.Customer)
    .Select(g => $"{g.Key} ({String.Join(", ", g.Select(cs => cs.Site).OrderBy(s => s))})")
    .ToArray();

string result = String.Join(", ", customersWithLocations);
Sign up to request clarification or add additional context in comments.

4 Comments

Just to make it clear: .ToArray() is not actually required in the first statement, because String.Join can accept IEnumerable<string> as an argument, but I personally prefer not to store IEnumerable<T> as local variables to avoid possible multiple enumeration, while combining them into a single statement would make code less readable and messy. It shouldn't notably affect performance, but you may remove .ToArray() if customersWithLocations is not used in code further.
OP states "I still have no clue how to deal with sorting (AFRICA --> AMERICA --> CHINA)". This answer doesn't address the sorting requirement.
@Jon, my bad, didn't notice it actually. I have update my answer, thanks!
I would add a .OrderBy(g => g.Key) after the GroupBy to sort the customers.
5

A one line LINQ statment can do it all:

var list = listCustomerSite
    .GroupBy(c => c.Customer)
    .Select(g => $"{g.Key} ({string.Join(", ", g.Select(c => c.Site))})")
    .ToList();

2 Comments

This actually does not fit the requirements 100%. OP wanted a single string result: "I would like to have 1 concatenated string". This is a list...
... nor does it address the requirement to have the output sorted alphabetically.
1

This should produce the desired output, sorted as required:

public class CustomerSite
{
    public CustomerSite(string customer, string site)
    {
        Customer = customer;
        Site = site;
    }

    public string Customer { get; set; }

    public string Site { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var listCustomerSite = new List<CustomerSite>()
        {
            new CustomerSite("SAMSUNG", "CHINA"),
            new CustomerSite("SAMSUNG", "AMERICA"),
            new CustomerSite("SAMSUNG", "AFRICA"),
            new CustomerSite("LG", "CHINA"),
            new CustomerSite("APPLE", "AMERICA"),
            new CustomerSite("APPLE", "CHINA")
        };

        var list = from cs in listCustomerSite
                   group cs by cs.Customer into g
                   orderby g.Key
                   select $"{g.Key} ({string.Join(", ", g.OrderBy(c => c.Site).Select(c => c.Site))})";

        Console.WriteLine(string.Join(", ", list));
        Console.ReadKey();
    }
}

Output:

APPLE (AMERICA, CHINA), LG (CHINA), SAMSUNG (AFRICA, AMERICA, CHINA)

Hope this helps!

Comments

1

The idea of using a dictionary is good; however, I would operate in two steps:

  1. Gather the data into sorted collections.
  2. Concatenate the customers and sites.

I'm not going to use LINQ, as it will be more instructive and show the fundamental way of doing things (since you are learning C#).

I am using a SortedDictionary<TKey, TValue> as it automatically sorts the entries by the key (the customers in our case).

var dictCustomer = new SortedDictionary<string, SortedSet<string>>();

The idea is to use the customer name as key and a sorted set of sites as value. A SortedSet<T> not only keeps the entries sorted, but also eliminates duplicates (which is not required here).

foreach (CustomerSite customerSite in listCustomerSite) {
    if (dictCustomer.TryGetValue(customerSite.Customer, out var siteSet)) {
        siteSet.Add(customerSite.Site);
    } else {
        siteSet = new SortedSet<string> { customerSite.Site };
        dictCustomer.Add(customerSite.Customer, siteSet);
    }
}

Now, let us build the result string:

var sb = new StringBuilder();
foreach (var keyValuePair in dictCustomer) {
    if (sb.Length > 0) {
        sb.Append(", ");
    }
    sb.Append(keyValuePair.Key).Append(" ("); // Appends the customer and " (".
    bool nextSite = false;
    foreach (string site in keyValuePair.Value) {
        if (nextSite) {
            sb.Append(", ");
        }
        sb.Append(site);
        nextSite = true;
    }
    sb.Append(")");
}
string result = sb.ToString();

Note that a StringBuilder is more efficient than concatenating strings directly, since a StringBuilder uses a buffer internally which grows only as needed, while string concatenation creates a new string object at each step and involves copying an ever-growing string over and over.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.