How does GroupBy in LINQ work?

12,619

Solution 1

Group by works by taking whatever you are grouping and putting it into a collection of items that match the key you specify in your group by clause.

If you have the following data:

Member name     Group code
Betty           123
Mildred         123
Charli          456
Mattilda        456

And the following query

var query = from m in members
            group m by m.GroupCode into membersByGroupCode
            select membersByGroupCode;

The group by will return the following results:

enter image description here

You wouldn’t typically want to just select the grouping directly. What if we just want the group code and the member names without all of the other superfluous data?

We just need to perform a select to get the data that we are after:

var query = from m in members
            group m by m.GroupCode into membersByGroupCode
            let memberNames = from m2 in membersByGroupCode
                              select m2.Name
            select new
            {
                GroupCode = membersByGroupCode.Key,
                MemberNames = memberNames
            };

Which returns the following results:

enter image description here

Solution 2

What values will go in to the lists that are returned for the group?

The first for each group, because you do:

.Select(x => x.First())

What happens to the rest of the values?

They will not be projected into your target dictionary.

Solution 3

Your LINQ group by query takes the original list, performs additional grouping on it, and then prunes the list based on that grouping.

Consider a situation where a single list contains these items:

GroupID GroupFin ZipCode Name
------- -------- ------- ----
      1        1   94111    A
      1        1   94111    B
      1        1   94111    C
      1        1   94111    D
      1        2   94110    E
      1        2   94110    F

Group by would make two groups out of this list of six:

GroupID=1 GroupFin=1 ZipCode=94111
GroupID=1 GroupFin=2 ZipCode=94110

The first group would contain providers A, B, C, and D; the second group would contain E and F.

The next thing that your query does is applying First. This operation picks the initial item from the group; in this case, it would be A and E. The remaining items are thrown ignored.

Share:
12,619
ConfusedSleepyDeveloper
Author by

ConfusedSleepyDeveloper

Updated on June 13, 2022

Comments

  • ConfusedSleepyDeveloper
    ConfusedSleepyDeveloper almost 2 years

    I originally have a dictionary of <string, List<ProviderSummary>> called rowsDictionary

    Now for each key of that dictionary I group its list of values by some criteria as below:

        Dictionary<string, List<ProviderSummary>> providerGroups = rowsDictionary.ToDictionary(
                x => x.Key,
                v => v.Value.GroupBy(x => new { x.GroupID, x.GroupFin, x.ZipCode })
                          .Select(x => x.First())
                          .ToList());
    

    so for example if key["1234"] originally had 6 items in its list of values, now it may have two items based on that grouping. My question and confusion is what happens to the rest of the values? ( those four) and what values will go in to these two lists that are returned for the group?

  • ConfusedSleepyDeveloper
    ConfusedSleepyDeveloper almost 10 years
    Thanks, so because I am grouping them there is no way I can still have all the values, Is there any way?
  • CodeCaster
    CodeCaster almost 10 years
    @ConfusedSleepyDeveloper then you should just omit the .Select(x => x.First()).
  • CodeCaster
    CodeCaster almost 10 years
    "for all practical purposes, you could consider this choice arbitrary" - Jon's blog, just as the documentation, claims "The IGrouping<TKey, TElement> objects are yielded in an order based on the order of the elements in source that produced the first key of each IGrouping<TKey, TElement>. Elements in a grouping are yielded in the order they appear in source". Won't this mean First() will always return A, E?
  • Sergey Kalinichenko
    Sergey Kalinichenko almost 10 years
    @CodeCaster You're right, .NET's hash dictionaries do have predictable ordering. Thanks!
  • ConfusedSleepyDeveloper
    ConfusedSleepyDeveloper almost 10 years
    Thanks I had tried that but it gives cannot convert source to target types error. Do you know what should I replace it with?