I have a dictionary, where the key is a string and the value is a list of strings that correspond to that key. I would like to display all of the keys in the dictionary, with the values associated with that key tabbed in underneath that key. Something like this:
Key 1
Value 1
Value 2
Value 3
Key 2
Value 1
Value 2
In C# 2.0, I would do that like this (values
is the Dictionary
):
StringBuilder sb = new StringBuilder();
foreach(KeyValuePair<string, List<string>> pair in values)
{
sb.AppendLine(pair.Key);
foreach(string item in pair.Value)
{
sb.AppendLine('\t' + item);
}
}
How would I do the equivalent using LINQ? It seems like it should be possible, however I can't figure out how to do it.
If I use values.SelectMany(p => p.Values)
, then only the values will be in the final result, not the keys as well.
Any other solution that I've thought of has a similar limitation.
Unfortunately, there is no built-in method for getting the key by value from a dictionary in C#.
In Dictionary, the key cannot be null, but value can be. In Dictionary, key must be unique. Duplicate keys are not allowed if you try to use duplicate key then compiler will throw an exception. In Dictionary, you can only store same types of elements.
Here is a solution using the aggregate extension method:
string result = values.Aggregate("",
(keyString, pair) =>
keyString + "\n" + pair.Key + ":"
+ pair.Value.Aggregate("",
(str, val) => str + "\n\t" + val)
);
There is no LINQ syntax for the aggregate clause in C# (but apparently there is in Visual Basic for some predefined functions).
This solution might look somewhat complex, but the aggregate method is quite useful.
It works like this: If you have a List<int>
you can combine all values into a single aggregate value.
That is in contrast to the Select
method, which doesn't modify the length of the list. Or the Where
method, which does shrink the list, but it still remains a list (instead of a single value).
For example, if you have a list {1, 2, 3, 4}
you can combine them into a single value like this:
int[] xs = {1, 2, 3, 4};
int sum = xs.Aggregate(0, (sumSoFar, x) => sumSoFar + x);
So you give two values to the Aggregate
method; a seed value and a 'combiner' function:
0
in this case).x
.That's in short how the Aggregate
method works on List<int>
. It works the same on KeyValuePair<string, List<string>>
, but just with different types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With