Использование GroupBy и Max в лямбда-выражениях LINQ

у меня есть коллекция, например:

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

Я хочу использовать LINQ и получить следующий результат:

**value**
   6
   87

П. С.

id1 - select MAX;
id2 - group column;

мне нужен ответ в виде

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

надеюсь на вашу помощь.

3 ответов


EDIT: хорошо, теперь у нас есть немного более четкий набор требований (хотя все еще далеко не ясно написано) самый простой подход, вероятно, будет:

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

к сожалению, LINQ не предоставляет простой способ получить "элемент с максимальным значением" (вместо самого максимального значения). У меня есть метод в MoreLINQ который делает это, хотя, называется MaxBy:

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

оригинальный ответ (группировка по ID2, которое, принимая максимальное значение)

я отвечаю предполагая, что вы на самом деле означало для группы id2, а не id1, и вы действительно хотели получить результаты 12 и 87, а не 6 и 87. В этом случае вы бы хотели:

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

или (возможно, проще для понимания):

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

или:

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

или:

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

или еще:

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

Как видите, GroupBy есть много перегрузок :)

или вы можете использовать выражение запроса:

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

вы не должны ограничивать себя или выражения запроса или версия метода расширения-важно понимать оба, поэтому вы можете использовать то, что наиболее подходит.


по-видимому, OP хочет Value максимум Id1 внутри Id2:

пример данных:

public class Row
{
    public int Id1;
    public int Id2;
    public int Value;
}

List<Row> rows = new List<Row>(){
    new Row(){Id1=1,Id2=9,Value=12},
    new Row(){Id1=2,Id2=9,Value=6},
    new Row(){Id1=3,Id2=11,Value=8},
    new Row(){Id1=4,Id2=11,Value=87}
};

устранение:

List<int> res = rows.GroupBy(r => r.Id2)
                    .Select(g => g.OrderByDescending(i=>i.Id1).First().Value)
                    .ToList();

в случае, если это помогает другим, у меня была аналогичная ситуация, за исключением нескольких записей, которые нужно было вернуть вместо одной записи.

например.

**id1, id2, value**
   1    9    12
   2    9     6 <-
   2    9     7 <-
   3    11    8
   4    11   87 <-
   4    11   88 <-

следующий возвращает выше четырех записей в виде двух списков из двух записей (перечисляемое enumerables):

 var maxes = from x in list
            group x by x.id2 into xs
            select new {values = xs.Where(x => x.id1 == xs.Max(y => y.id1))};

или

 var maxes = list.GroupBy(x => x.id2,
            (key, xs) => new
            {
                values = xs.Where(x => x.id1 == xs.Max(y => y.id1))
            });