如何使用 Linq 获得每组的第一个记录

考虑到以下记录:

   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 做到这一点?

138450 次浏览
var result = input.GroupBy(x => x.F1, (key,g) => g.OrderBy(e => e.F2).First());
var res = from element in list
group element by element.F1
into groups
select groups.OrderBy(p => p.F2).First();

@ Alireza 的 awnser 是完全正确的,但是您必须注意,当使用此代码时

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

使用它来实现你想要的。然后决定你想要返回哪些属性。

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
var res = (from element in list)
.OrderBy(x => x.F2).AsEnumerable()
.GroupBy(x => x.F1)
.Select()

在 OrderBy ()之后使用

另一种方式:

var result = input.GroupBy(i => i.F1).Select(g => g.First());

您可以按多个字段进行分组:

var result = input.GroupBy(i => new {i.F1, i.F2}).Select(g => g.First());

如果你需要保持秩序,那么使用查找:

var result = input.ToLookup(i => i.F1).Select(g => g.First());

这不是你想要的,但有时我们会找错东西,因为我们不知道什么存在。因此,我发现最直观的解决办法是:

var dict =
input.OrderByDescending(x => x.Id)
.GroupBy(x => x.F1)
.ToDictionary(x => x.Key, x => new { x.First().F1, x.First().F2, x.First().F3});

第一个顺序,然后组-直线前进。现在得到的结果将是一个键类型对的列表 something。因为我们的表已经排序了,所以我们只需选择第一个条目。另外,我建议将结果放入一个以 ID 作为访问器的字典中,这是一个访问速度非常快的数据结构,而且仍然具有灵活性。现在您可以使用

dict[4].F1 // returns Nima

Something 从技术上讲,它是 IEnumable < IGrouping < int,yourType > >