Search code examples
c#linqdictionarygroup-bygrouping

Apply Group by to dictionary value


I have a Dictionary which key of string type and value of list of integer type, like this: Dictionary<string, List<int>>.

Lets say I add elements to it:

Dictionary<string, List<int>> check2 = new Dictionary<string, List<int>>();     
check2.Add("LD010101", new List<int> { 1, 2, 3 });
check2.Add("LD010201", new List<int> { 1 });
check2.Add("LD030101", new List<int> { 2, 3, 4 });
check2.Add("LD030201", new List<int> { 1, 3, 4 });
check2.Add("LD040101", new List<int> { 5, 1, 4 });
check2.Add("LD050101", new List<int> { 1, 3, 4 });

Now I want to apply group by based on the integer value and filter it. Let's say group by filter is 2. Then the output has to be a dictionary like this Dictionary<int, List<string>>, so with filter 2, the output will be a dictionary like this, and I have to use GroupBy to do this:

key:2, Value: {"LD010101","LD030101"}

Solution

  • This method is an example, giving the first Dictionary<int, List<string>> and the filter as parameters, and returning a new Dictionary<int, List<string>> that groups the first keys by the filter.

    public static Dictionary<int, List<string>> FilterDictionaryByGroup(Dictionary<string, List<int>> inputDict, int filter)
        {
            var grouped = inputDict
                .Where(el => el.Value.Contains(filter))
                .GroupBy(el => filter)
                .ToDictionary(g => g.Key, g => g.Select(el => el.Key).ToList());
    
            return grouped;
        }
    
    var result = FilterDictionary(check2, filter);
    

    Bare in mind that this approach handles only dealing with one filter value (in your case 2 for example), but since you want the return type to be Dictionary<int, List<string>>, you can still adhere to the same approach by adding List<int> filters to the method args instead of a single int, and iterate over them.

    Edit

    The Where clause is self-explanatory, it iterates through each element and "filters" them by returning only the elements where their values List contains the filter (here 2 for example, since that's only what we want).

    g.Select(el => el.Key) means "for each element (el) in the group (g), select its key". This extracts the keys of all the dictionary entries in the group.

    ToList() converts the selected keys into a list. This is necessary since we want the value of dictionary element to be a List<string> and not the generic IEnumerable<string> that Select returns.