Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you explain this lambda grouping function?

I've been using LINQ and Lambda Expressions for a while, but I'm still not completely comfortable with every aspect of the feature.

So, while I was working on a project recently I needed to get a distinct list of objects based off of some property, and I ran across this code. It works, and I'm fine with that, but I'd like to understand the grouping mechanism. I don't like simply plugging code in and running away from the problem if I can help it.

Anyways the code is:

var listDistinct
    =list.GroupBy(
        i => i.value1,
        (key, group) => group.First()
    ).ToList();

In the code sample above, you're first calling GroupBy and passing it a lambda expression telling it to group by the property value1. The second section of the code is causing the confusion.

I understand that key is referencing value1 in the (key, group) statement, but I'm still not wrapping my head around everything that's taking place.

like image 875
elucid8 Avatar asked Feb 28 '13 15:02

elucid8


2 Answers

What does the expression

list.GroupBy(
    i => i.value1,
    (key, group) => group.First())

do?

This creates a query which, when executed, analyzes the sequence list to produce a sequence of groups, and then projects the sequence of groups into a new sequence. In this case, the projection is to take the first item out of each group.

The first lambda chooses the "key" upon which the groups are constructed. In this case, all items in the list which have the same value1 property are put in a group. The value that they share becomes the "key" of the group.

The second lambda projects from the sequence of keyed groups; it's as though you'd done a select on the sequence of groups. The net effect of this query is to choose a set of elements from the list such that each element of the resulting sequence has a different value of the value1 property.

The documentation is here:

http://msdn.microsoft.com/en-us/library/bb549393.aspx

If the documentation is not clear, I am happy to pass along criticisms to the documentation manager.

This code uses group as the formal parameter of a lambda. Isn't group a reserved keyword?

No, group is a contextual keyword. LINQ was added to C# 3.0, so there might have already been existing programs using group as an identifier. These programs would be broken when recompiled if group was made a reserved keyword. Instead, group is a keyword only in the context of a query expression. Outside of a query expression it is an ordinary identifier.

If you want to call attention to the fact that it is an ordinary identifier, or if you want to use the identifier group inside a query expression, you can tell the compiler "treat this as an identifier, not a keyword" by prefacing it with @. Were I writing the code above I would say

list.GroupBy(
    i => i.value1,
    (key, @group) => @group.First())

to make it clear.

Are there other contextual keywords in C#?

Yes. I've documented them all here:

http://ericlippert.com/2009/05/11/reserved-and-contextual-keywords/

like image 155
Eric Lippert Avatar answered Oct 04 '22 18:10

Eric Lippert


I would like to simplify this to a list of int and how to do distinct in this list by using GroupBy:

var list = new[] {1, 2, 3, 1, 2, 2, 3};

if you call GroupBy with x => x, you will get 3 groups with type:

IEnumerable<IEnumerable<int>>

{{1,1},{2,2,2},{3,3}}

The key of each group are: 1, 2, 3. And then, when calling group.First(), it means you get first item of each group:

{1,1}: -> 1.
{2,2,2}: -> 2
{3,3} -> 3

So the final result is : {1, 2, 3}

Your case is similar with this.

like image 22
cuongle Avatar answered Oct 04 '22 20:10

cuongle