2013-05-29 115 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」。