Jak zdobyć pierwszy rekord w każdej grupie za pomocą Linq

133

Biorąc pod uwagę następujące zapisy:

   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

Chcę pogrupować według F1pola i posortować według Idi pobrać wszystkie pola z pierwszego rekordu grupy podobnej do tych rekordów:

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

Jak mogę to zrobić za pomocą linq?

ariański
źródło

Odpowiedzi:

127
    var res = from element in list
              group element by element.F1
                  into groups
                  select groups.OrderBy(p => p.F2).First();
Alireza
źródło
4
Tak się cieszę, że to znalazłem. Otrzymałem komunikat o błędzie „Metoda„ First ”może być używana tylko jako ostateczna operacja kwerendy. Rozważ użycie metody„ FirstOrDefault ”w tym przypadku." z twojego przykładu. Jedyna operacja na liście, którą wykonałem po zapytaniu, przekazywała myResult.ToList () do metody. Użycie FirstOrDefault rozwiązało problem
aghost
Czyżby tak OrderBy(p => p.Id), chcieli, żeby to było uporządkowane według dowodu osobistego, a nie kolumny roku.
Mike Flynn
Czy możesz
udzielić
A jeśli chcesz odzyskać pierwszą i ostatnią pozycję z grupy?
Sandeep Pandey
176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());
King King
źródło
2
To pokazało mi sposób używania składni Fluent. Wydaje się, że przeciążenia związane z GroupBy dają ci dużą moc - jedną do dodania do długiej listy nauki!
rogersillito,
1
@rogersillito dlatego nazywa się to zapytaniem (Language Integrated Query - LINQ), również GroupBy ma wiele przeciążeń, ale jest ich tylko kilka, które są powszechnie używane, również zależy to od osobistych preferencji, na przykład niektórzy wolą pisać to jako .GroupBy(x=>x.F1).Select(g=>...), może wydawać się łatwiejsze do zrozumienia.
King King,
11
Należy wymienić .First()z .FirstOrDefault()lub dostaniesz wyjątek:The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Nikolay Kostov
5
@NikolayKostov Wiem o tym, ale założyłem, że LINQ jest tutaj używany jako LINQ-to-object, a nie LINQ-to-entity, więc możemy bezpiecznie używać .First(). Pytanie OP wygląda tak, jakby po prostu dbał o łączenie się z obiektem, chociaż oznaczył je również tagiem linq-to-entities(nie jestem pewien, czy rozumiał, co to jest).
King King
1
Podobały mi się te odpowiedzi, niezła.
Ajas Aju
8

Awnser @Alireza jest całkowicie poprawny, ale musisz to zauważyć, używając tego kodu

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

który jest podobny do tego kodu, ponieważ porządkujesz listę, a następnie grupujesz, więc otrzymujesz pierwszy wiersz grup

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

Teraz, jeśli chcesz zrobić coś bardziej złożonego, na przykład wziąć ten sam wynik grupowania, ale wziąć pierwszy element F2 i ostatni element F3 lub coś bardziej niestandardowego, możesz to zrobić, studiując poniższy kod

 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;
           });

Więc dostaniesz coś takiego

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4
Stavros Koureas
źródło
Separator lub separator nowego obiektu powinien być przecinkiem, a nie średnikiem. Sprawdź.
Naredla Nithesh Reddy
3

Użyj go, aby osiągnąć to, czego chcesz. Następnie zdecyduj, które właściwości chcesz zwrócić.

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
Rubens Mussi Cury
źródło