Home > Mobile >  Group by elements of a value
Group by elements of a value

Time:07-30

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.

  • Related