public class Person
{
public int Id {get;set;}
public int PersonId {get;set;}
public string University {get;set;}
public string Department {get;set;}
public DateTime GraduatedDate {get;set;}
}
List<Person> list = new List<Person>();
list.Add(new Person { 1, 1, "Shota Rustavelli University", "Computer Science BS", "10.12.2005" });
list.Add(new Person { 2, 1, "Shota Rustavelli University", "Computer Science MS", "10.12.2005" });
list.Add(new Person { 3, 2, "Tblisi State University", "Mathematics BS", "10.12.2004" });
list.Add(new Person { 4, 3, "Shota Rustavelli University", "Economics BS", "10.12.2006" });
list.Add(new Person { 5, 3, "Tblisi State University", "Economics MS", "10.12.2006" });
list.Add(new Person { 6, 1, "Georgian Technical University", "Mathemetics Phd", "10.12.2009" });
foreach(var item in (list.GroupBy(m=> new{m.PersonId,m.University,m.Department})).Max(m=>m.GraduatedDate))
{
item.PersonId
item.University
item.Department
}
我是如何根据PersonId使用以下结构获得上一个大学和部门。我曾尝试使用LINQ GroupBy和Max,但我得到了错误。
答案 0 :(得分:2)
Max(m=>m.GraduatedDate)
会为您带来:GraduatedDate
在集合中的最大值。在您的情况下,它不会编译,因为您将它应用于没有GraduatedDate
属性的项目集合。
为了获得每人的最后一次毕业,您可以使用以下LINQ查询:
var results =
list
.GroupBy(m => m.PersonId)
.Select(g => new {
PersonId = g.Key,
LastGraduation = g.OrderByDescending(p => p.GraduatedDate).First()
});
结果可以像这样显示,例如:
foreach(var r in results){
Console.WriteLine("{0}, {1}, {2}",
r.PersonId,
r.LastGraduation.University,
r.LastGraduation.Department);
}
以下是一个ideone代码段,其中显示了此版本的运行版本:http://ideone.com/em4Ygq
请注意,我已将GraduatedDate
更改为string
,以便更好地匹配初始化列表的方式。我应该声明为DateTime
并相应地进行初始化。
答案 1 :(得分:1)
虽然您可以使用GroupBy和Max返回最新的人员条目,但使用MoreLINQ的MaxBy运算符返回具有最大谓词的元素会更容易且更快捷:
IEnumerable<Person> personEntries=list.GroupBy(p => p.PersonId)
.Select(g => g.MaxBy(p => p.GraduatedDate));
您可以将MoreLINQ库添加为single NuGet package,或者只添加所需运算符的源代码,例如MaxBy
这些运算符比GroupBy更快并且排序的原因是MaxBy / MinBy运算符不对列表的元素进行排序,而是简单地遍历所有项目,仅保留对它们遇到的最大/最小项目的引用。这比排序要快得多。
在PLINQ场景中,MaxBy / MinBy是必不可少的,因为排序会引入锁定和同步,这可能会使您的PLINQ查询运行速度比顺序版本慢。