Как получить первую запись в каждой группе, используя Linq

133

Учитывая следующие записи:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   2           Nima          1990           11
   3           Nima          2000           12
   4           John          2001           1
   5           John          2002           2 
   6           Sara          2010           4

Я хочу сгруппировать по F1полям, отсортировать по Idи получить все поля из первой записи группы, подобные этим записям:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   4           John          2001           1
   6           Sara          2010           4

Как я могу сделать это с помощью Linq?

ариец
источник

Ответы:

127
    var res = from element in list
              group element by element.F1
                  into groups
                  select groups.OrderBy(p => p.F2).First();
Алиреза
источник
4
Так рад, что нашел это. Я получил сообщение об ошибке: «Метод« Первый »можно использовать только как окончательную операцию запроса. Вместо этого рассмотрите возможность использования метода« FirstOrDefault »в этом случае». из вашего примера. Единственная операция в списке, которую я сделал после того, как запрос передал метод myResult.ToList (). Использование FirstOrDefault решило эту проблему
aghost
Было бы OrderBy(p => p.Id), они хотели, чтобы это заказало удостоверение личности не колонка года.
Майк Флинн
Подскажите,
Что если вы хотите получить первый и последний элемент из группы?
Сандип Пандей
176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());
Король король
источник
2
Это показало мне путь, используя свободный синтаксис. В перегруженных для GroupBy появляется , чтобы дать вам много энергии - один , чтобы добавить к длинному списку обучения!
rogersillito
1
@rogersillito, именно поэтому он называется запросом (Language Integrated Query - LINQ), также GroupBy имеет много перегрузок, но обычно используются лишь некоторые из них, также это зависит от личных предпочтений, например, некоторые предпочитают писать его как .GroupBy(x=>x.F1).Select(g=>...), это может выглядеть проще для понимания.
король король
11
Вам следует заменить .First()на .FirstOrDefault()или вы получите исключение:The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Николай Костов
5
@NikolayKostov Я знаю об этом, но я предположил, что LINQ здесь используется как LINQ-to-object, а не LINQ-to-entity, поэтому мы можем безопасно использовать его .First(). Вопрос ОП выглядит просто как забота о linq-to-object, хотя он также пометил вопрос linq-to-entities(не уверен, понял ли он, что это такое).
Король Король
1
Мне понравились эти ответы, Хороший.
Аджас Аю
8

Замечатель @Alireza совершенно правильный, но вы должны заметить, что при использовании этого кода

var res = from element in list
          group element by element.F1
              into groups
              select groups.OrderBy(p => p.F2).First();

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

var res = (from element in list)
          .OrderBy(x => x.F2)
          .GroupBy(x => x.F1)
          .Select()

Теперь, если вы хотите сделать что-то более сложное, например, взять тот же результат группировки, но взять первый элемент F2 и последний элемент F3 или что-то более нестандартное, вы можете сделать это, изучив код ниже

 var res = (from element in list)
          .GroupBy(x => x.F1)
          .Select(y => new
           {
             F1 = y.FirstOrDefault().F1;
             F2 = y.First().F2;
             F3 = y.Last().F3;
           });

Таким образом, вы получите что-то вроде

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4
Ставрос Куреас
источник
1
Разделитель или разделитель нового объекта должен быть запятой, а не точкой с запятой. Пожалуйста, проверьте.
Наредла Нитеш Редди
3

Используйте это, чтобы достичь того, что вы хотите. Затем решите, какие свойства вы хотите вернуть.

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
Рубенс Мусси Кьюри
источник