String concatenation C# with List of Class

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



String concatenation C# with List of Class



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;


CustomerSite


string Customer get;set


string Site get;set;



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


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)"


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)


(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 + ")");






maybe offtopic for your question but keep in mind that a dictionary doesn't guarantee the insertion order.
– gsharp
Aug 10 at 16:45




4 Answers
4



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:


String.Join


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);





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.
– Yeldar Kurmangaliyev
Aug 10 at 16:19



.ToArray()


String.Join


IEnumerable<string>


IEnumerable<T>


.ToArray()


customersWithLocations





OP states "I still have no clue how to deal with sorting (AFRICA --> AMERICA --> CHINA)". This answer doesn't address the sorting requirement.
– Jon
Aug 10 at 16:21





@Jon, my bad, didn't notice it actually. I have update my answer, thanks!
– Yeldar Kurmangaliyev
Aug 10 at 16:22





I would add a .OrderBy(g => g.Key) after the GroupBy to sort the customers.
– Olivier Jacot-Descombes
Aug 10 at 16:31


.OrderBy(g => g.Key)


GroupBy





Thank you very much - works perfectly
– Secret
Aug 10 at 17:11



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();





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...
– maccettura
Aug 10 at 16:09



"I would like to have 1 concatenated string"





... nor does it address the requirement to have the output sorted alphabetically.
– Jon
Aug 10 at 16:20



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!



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



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).


SortedDictionary<TKey, TValue>


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).


SortedSet<T>


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.


StringBuilder


StringBuilder






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard