Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using GroupBy and Max in LINQ Lambda Expressions

I have a collection, for example:

**id1, id2, value**
   1    9    12
   2    9     6
   3    11    8
   4    11   87

I want to use LINQ and get the following result:

**value**
   6
   87

P.S.

id1 - select MAX;
id2 - group column;

I need an answer in the form of

var result = list.GroupBy(x=>x.id2).select(s=>s.value);

I hope for your help.

like image 519
Pavel Avatar asked Apr 07 '13 18:04

Pavel


People also ask

What does GroupBy do in LINQ?

GroupBy<TSource,TKey,TElement>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TSource,TElement>) Groups the elements of a sequence according to a specified key selector function and projects the elements for each group by using a specified function.

Is LINQ faster than lambda?

In some cases LINQ is just as fast if not faster than other methods, but in other cases it can be slower. We work on a project that we converted to linq and the data lookup is faster but the merging of data between two tables is much slower.

What is the difference between Lambda expression and LINQ?

As such, lambdas aren't equivalent to LINQ, they're a shorthand syntax for anonymous functions. However, they're a stepping stone towards LINQ. LINQ is, in its essence, a way to filter, transform and manipulate collections using techniques borrowed from functional programming.

What is Lambda expression in LINQ?

A lambda expression is a convenient way of defining an anonymous (unnamed) function that can be passed around as a variable or as a parameter to a method call. Many LINQ methods take a function (called a delegate) as a parameter.


1 Answers

EDIT: Okay, now we've got a slightly clearer set of requirements (though still far from clearly written) the simplest approach would probably be:

var maxes = list.GroupBy(x => x.id2,
                         (key, xs) => xs.OrderByDescending(x => x.id1)
                                        .First()
                                        .value);

Unfortunately LINQ doesn't provide a simple way of getting "the element with the maximal value" (instead of the maximal value itself). I have a method in MoreLINQ which does this though, called MaxBy:

var maxes = list.GroupBy(x => x.id2,
                         (key, xs) => xs.MaxBy(x => x.id2).value);

Original answer (Grouping by id2, taking the maximum value)

I'm answering assuming you actually meant to group by id2 rather than id1, and you actually wanted the results of 12 and 87 rather than 6 and 87. In that case, you'd want:

var maxes = list.GroupBy(x => x.id2, (id, xs) => xs.Max(x => x.value));

Or (possibly simpler to understand):

var maxes = list.GroupBy(x => x.id2)
                .Select(xs => xs.Max(x => x.value));

Or:

var maxes = list.GroupBy(x => x.id2, x => x.value)
                .Select(values => values.Max());

Or:

var maxes = list.GroupBy(x => x.id2,     // Key selector
                         x => x.value,   // Element selector
                         (key, values) => values.Max()); // Result selector

Or even:

var maxes = list.GroupBy(x => x.id2)
                .Select(xs => xs.Select(x => x.value).Max());

As you can see, GroupBy has lots of overloads :)

Or you could use a query expression:

var maxes = from x in list
            group x.value by x.id2 into values
            select values.Max();

You shouldn't restrict yourself to either query expressions or the extension method version - it's important to understand both, so you can use whatever's most appropriate.

like image 134
Jon Skeet Avatar answered Sep 18 '22 00:09

Jon Skeet