Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concat all strings from dictionary (values) using LINQ without external variable

Having dictionary where key can be anything (e.g. int) and values is some text I want to output.

Dictionary<int, string> dict = new Dictionary<int, string>();

dict.Add(1, "This is the first line.");
dict.Add(2, "This is the second line.");
dict.Add(3, "This is the third line.");

To get output:

string lResult = dict. ... //there should go the LINQ query
Console.WriteLine(lResult);

Output:

This is the first line.
This is the second line.
This is the third line.

Q: Is it possible to concatenate the lines from Dictionary to have them as one string without using external variable?


I tried approach using some Select/SelectMany/Zip solutions, but I cannot figure how to pass the value from 1 LINQ call to other without using external variable.

Another idea is to Select values, put them to the List and then Concatenate (again using external variable). Like:

string tmp = "";
dict.Select(a => a.Value).ToList().ForEach(b => tmp += b);
like image 299
Tatranskymedved Avatar asked Jan 31 '18 09:01

Tatranskymedved


4 Answers

You shouldn't use LINQ to concat strings. This can become very expenisve. Use string.Join() innstead:

string result = string.Join(Environment.NewLine, dict.Values);

However, this does not guarantee the correct order, because a Dictionary<> is not sorted. To sort the output by the Keys you can do this:

string sorted = string.Join(Environment.NewLine, 
                     dict.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value));
like image 110
René Vogt Avatar answered Nov 10 '22 12:11

René Vogt


You can do:

string.Join(Environment.NewLine, dict.Values)

Note however, that the documentation states the values will be retrieved in an unspecified order.

like image 37
Cristian Lupascu Avatar answered Nov 10 '22 13:11

Cristian Lupascu


I suggest using StringBuilder if you want to use LINQ. Otherwise the performance will suffer too much:

string lResult = dict.Values.Aggregate(new StringBuilder(), (a, b) => a.Append(b)).ToString()
like image 22
Schmid Avatar answered Nov 10 '22 12:11

Schmid


Appending string in a loop

ForEach(b => tmp += b)

is an antipattern; you should use StringBuilder. In case you have to use Linq (not string.Join which is specially designed for it):

  dict.Add(1, "This is the first line.");
  dict.Add(2, "This is the second line.");
  dict.Add(3, "This is the third line.");

  string result = dict
    .OrderBy(pair => pair.Key)
    .Aggregate((StringBuilder) null, 
               (sb, pair) => (sb == null 
                  ? new StringBuilder() 
                  : sb.Append(Environment.NewLine)).Append(pair.Value))
    .ToString();
like image 1
Dmitry Bychenko Avatar answered Nov 10 '22 14:11

Dmitry Bychenko