2013-05-29 193 views
3

所以,我有一个看起来像这样的列表。它基本上是一堆物品的状态历史记录,最近的状态代表当前状态。Linq查询分组项目和从每个组中的顶部项目查询

Record Id  State  Date 
===== ===  ========= ======= 
1  A  Waiting  Jan 01 
2  A  InProgress Jan 02 
3  A  Finished Jan 03 
4  B  Waiting  Jan 02 
5  C  Waiting  Jan 01 
6  C  InProgress Jan 02 
7  D  Waiting  Jan 01 
8  D  InProgress Jan 02 

我在找的是能够查询每个项目的'当前'状态。例如,我想说:“给我所有的Ids都是'InProgress''”并获得Id D和Id C,但不是Id A(因为它的最新状态是'Finished')。

我知道我必须做一些分组和一些订购或Maxing,但我不能把它放在一起。

+2

你到目前为止尝试过什么?向我们展示你在分组排序和最大化方面所做的工作,并且我们可以告诉你哪里出错了。对于学习来说,不仅仅是获得解决方案更好...... – Chris

回答

9
myList.GroupBy(m => m.Id) 
.Select(g => g.OrderByDescending(x => x.Date).First()) 
.Where(<your filter>); 
1

如果是这样的LINQ to(被安排在正确的顺序,并假设记录)的对象,你可以这样做:

var latestById = records.GroupBy(record => record.Id) 
         .ToDictionary(group => group.Key, group => group.Last()); 

这是因为的GroupBy在分组guarantees that“分子产生的为了它们出现在源代码中“。

如果你不能对记录顺序的保证,我会做:

var latestById = records.GroupBy(record => record.Id) 
         .Select(group => group.MaxBy(r => r.Date)) 
         .ToDictionary(record => record.Id); 

其中MaxBy来自moreLinq

顺便说一句,如果这是LINQ to SQL的,我会做:

var latestById = records.GroupBy(record => record.Id) 
         .Select(group => group.OrderByDescending(r => r.Date).First()) 
         .AsEnumerable() 
         .ToDictionary(record => record.Id); 
+0

我们不知道他们在源文件中出现的顺序是否是日期顺序?他们在这个例子中,但他没有说记录是按日期顺序的。 Nitpicky,但它是错误的源泉... – Chris

+0

@Chris:似乎是这样,但我提供了一种方式,如果不是这样的话。 – Ani

+0

谢谢Ani。我认为这是一个更好的答案。 :) – Chris

2

下面是一些代码,做你想做的。它获取每个ID的最新状态并忽略完成的记录。我提供了一个可以运行的完整工作示例(并且希望能够适应您的真实数据)。

//the example data provided by the OP 
var data = new [] 
{ 
    new { Record = 1, Id = "A", State = "Waiting", Date = new DateTime(2013, 1, 1) }, 
    new { Record = 2, Id = "A", State = "InProgress", Date = new DateTime(2013, 1, 2) }, 
    new { Record = 3, Id = "A", State = "Finished", Date = new DateTime(2013, 1, 3) },   
    new { Record = 4, Id = "B", State = "Waiting", Date = new DateTime(2013, 1, 1) },   
    new { Record = 5, Id = "C", State = "Waiting", Date = new DateTime(2013, 1, 1) }, 
    new { Record = 6, Id = "C", State = "InProgress", Date = new DateTime(2013, 1, 2) },   
    new { Record = 7, Id = "D", State = "Waiting", Date = new DateTime(2013, 1, 1) }, 
    new { Record = 8, Id = "D", State = "InProgress", Date = new DateTime(2013, 1, 2) }, 
}; 

var query = from d in data 
      //put the newest record first 
      orderby d.Date descending 
      //group by the id 
      group d by d.Id into groupedById 
      //get the latest record for each id 
      let latest = groupedById.First() 
      //filter out finished records 
      where latest.State != "Finished" 
      select latest; 

这里是LinqPad的输出。

enter image description here

你会发现,我们有最新的状态,对每个项目,除了因为它完成其已被忽略“A”。