我的具体例子相当复杂,但我认为这个概念同样适用于日志记录系统之类的东西,因此为了便于解释,我将使用它.这是一个虚构的例子,请不要对这个例子本身的架构,编程或道德错误进行抨击或痛苦:)
说你有这个:
class LogEntry { int ID; int UserName; datetime TimeStamp; string Details; }
你已经提取了一组这样的数据:
ID Username Timestamp Details 1 foo 1/01/2010 Account created 2 zip 2/02/2010 Account created 3 bar 2/02/2010 Account created 4 sandwich 3/03/2010 Account created 5 bar 5/05/2010 Stole food 6 foo 5/05/2010 Can't find food 7 sandwich 8/08/2010 Donated food 8 sandwich 9/09/2010 Ate more food 9 foo 9/09/2010 Ate food 10 bar 11/11/2010 Can't find food
我想要做的是为每个用户选择最后一条记录(即TimeStamp Descending排序)(即GroupBy用户名).我可以把我的头围绕在Distinct上,并且在较小程度上将GroupBy放在一边,但是将所有这些组合在一个单独的语句中,该语句也返回非时间/分组的字段/属性和按时间戳排序让我头疼.
上面的例子应该是什么:
ID Username Timestamp Details 2 zip 2/02/2010 Account created 8 sandwich 9/09/2010 Ate more food 9 foo 9/09/2010 Ate food 10 bar 11/11/2010 Can't find food
当性能在这里并不重要时,我不想“欺骗”并采用冗长的方式来做这件事,而且我有点相信它可以在一个LINQ语句中完成.
解决方法
希望我的Linq-fu在这一个是正确的:=)
var results = sourceList .OrderByDescending(item => item.Timestamp) .GroupBy(item => item.Username) .Select(grp => grp.First()) .ToArray();
此示例代码使用您的数据,并按ID进行最终排序,提供与您的示例完全相同的输出:(如果您不介意原始格式!)
class Program { static void Main(string[] args) { var sourceItems = new[] { new LogEntry {ID=1,UserName="foo ",TimeStamp= new DateTime(2010,1,01),Details="Account created ",},new LogEntry {ID=2,UserName="zip ",2,02),new LogEntry {ID=3,UserName="bar ",new LogEntry {ID=4,UserName="sandwich ",3,03),new LogEntry {ID=5,5,05),Details="Stole food ",new LogEntry {ID=6,Details="Can't find food ",new LogEntry {ID=7,8,08),Details="Donated food ",new LogEntry {ID=8,9,09),Details="Ate more food ",new LogEntry {ID=9,Details="Ate food ",new LogEntry {ID=10,11,11),}; var results = sourceItems .OrderByDescending(item => item.TimeStamp) .GroupBy(item => item.UserName) .Select(grp => grp.First()) .OrderBy(item=> item.ID) .ToArray(); foreach (var item in results) { Console.WriteLine("{0} {1} {2} {3}",item.ID,item.UserName,item.TimeStamp,item.Details); } Console.ReadKey(); } } public class LogEntry { public int ID; public string UserName; public DateTime TimeStamp; public string Details; }