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
これを見つけてうれしい。「メソッド 'First'は最後のクエリ操作としてのみ使用できます。代わりに、このインスタンスではメソッド 'FirstOrDefault'の使用を検討してください。」というエラーメッセージが表示されました。あなたの例から。クエリがmyResult.ToList()をメソッドに渡した後に行ったリストに対する操作のみ。FirstOrDefaultを使用することで解決しました
aghost

それOrderBy(p => p.Id)は、年列ではなくIDで注文したかったのでしょう。
マイクフリン

あなたは、プロバイダを喜ばせることができ、このためのいくつかの支援:stackoverflow.com/questions/44764687/...
SI8

グループから最初と最後のアイテムを取得したい場合はどうなりますか?
Sandeep Pandey

176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());

2
これにより、Fluent構文の使用方法がわかりました。GroupByオーバーロードはあなたに多くの力を与えるようです-学習の長いリストに追加するための1つ!
rogersillito 2014

1
@rogersillitoは、クエリ(Language Integrated Query-LINQ)と呼ばれる理由です。また、GroupByには多くのオーバーロードがありますが、一般的に使用されているものはわずかですが、個人的な好みにも依存します。たとえば.GroupBy(x=>x.F1).Select(g=>...)、理解しやすく見えるかもしれません。
キングキング14

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-entitiesではなくLINQ-to-objectとして使用されると想定しているため、安全に使用できます.First()。OPの質問は、linq-to-objectを気にするだけのように見えますが、タグを付けましたlinq-to-entities(それが何であるかを理解しているかどうかはわかりません)。
キングキング

1
私はこの答えが好きでした。
Ajas Aju

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
新しいオブジェクトの区切り文字またはセパレータはセミコロンではなくカンマにする必要があります。確認してください。
Naredla Nithesh Reddy

3

あなたが望むものを達成するためにそれを使用してください。次に、返すプロパティを決定します。

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.