Использование 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))
});