如何使用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执行此操作?

Answers:


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而不是Year列进行排序。
Mike Flynn

您能为此提供一些帮助吗?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过载似乎为您提供了很多功能-一种可以添加到一长串学习中的功能!
rogersillito 2014年

1
@rogersillito这就是为什么它被称为查询(Language Integrated Query-LINQ)的原因,GroupBy也有很多重载,但是只有一些经常使用,它还取决于个人喜好,例如某些人更喜欢将其写为.GroupBy(x=>x.F1).Select(g=>...),它可能看起来更容易理解。
King King

11
您应该替换为.First().FirstOrDefault()否则您将得到例外: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我知道这一点,但是我假设这里的LINQ用作LINQ到对象,而不是LINQ到实体,因此我们可以放心使用.First()。OP的问题看上去确实像只是关心linq-to-object,尽管他也用这个问题标记了这个问题linq-to-entities(不确定他是否理解这是什么)。
King King

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

新对象的定界符或分隔符应为逗号而不是半冒号。请检查。
Naredla Nithesh Reddy

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.