I have 3 KeyValuePairs:
var dict = new Dictionary<string, List<int>>
{
["a"] = new List<int>{1,2},
["b"] = new List<int>{2,3},
["c"] = new List<int>{4,5}
};
I need to group it by the same elements, so as result I expect to have as follows:
var result = new Dictionary<List<string>, List<int>>
{
[new List<string> { "a"}] = new List<int> { 1 },
[new List<string> { "b"}] = new List<int> { 3 },
[new List<string> { "a", "b"}] = new List<int> { 2 },
[new List<string> { "c"}] = new List<int> { 4, 5 }
};
What would the best ways to get the result?
CodePudding user response:
First, you can use SelectMany
to flatten the data structure. This leads to the following structure:
a | 1
a | 2
b | 2
b | 3
c | 4
c | 5
You can then group these data by the integers, so that you receive the following groups:
1 | a
2 | a, b
3 | b
4 | c
5 | c
After that, you can again group by the character sets, so that you have the following result:
1 | a
2 | a, b
3 | b
4, 5 | c
You can convert this into a dictionary (but be careful with lists as dictionary keys - lists are mutable so that you might not be able to find the elements later on; also lists are compared by reference if there is no comparer specified).
The following code creates the groups:
var grouped = dict
.SelectMany(x => x.Value.Select(y => new { i = y, k = x.Key }))
.GroupBy(x => x.i)
.Select(x => new { Key = x.Select(y => y.k).ToList(), Value = x.Key })
.GroupBy(x => string.Join("|", x.Key.OrderBy(x => x)))
.Select(x => new { Key = x.First().Key, Value = x.Select(y => y.Value).ToList() });
var result = grouped.ToDictionary(x => x.Key, x => x.Value);
See this fiddle to test.