2011-09-15 35 views
1

我有一個列表list與它類似的商品沒有MAX()適用:序列不包含任何元素

ElementA: Number=1, Version=1 
ElementB: Number=1, Version=2 
ElementC: Number=1, Version=3 <- 
ElementD: Number=2, Version=1 
ElementE: Number=2, Version=2 <- 
ElementF: Number=3, Version=1 <- 

,我想選擇其中有一個組中的最高Version與同一項目的所有項目Number。 (見箭頭上方。)

我想用這個查詢,所以我已經試過這樣:

var result = from a in list where a.Version >= 
      (from b in list where b.Number == a.Number && b != a select b.Version).Max() select a; 

這是工作的罰款,如果每個項目組與同Number由至少包含2個元素,否則如果內部查詢不包含任何元素,則會引發InvalidOperationException。

如何重寫查詢以獲取我想要的內容?我會感激每一個提示。 :-)

回答

4

這應該做的伎倆,但不復制數據我自己,我不能測試:

var result = 
    list.GroupBy(x => x.Number) 
     .Select(gr => 
        gr.OrderByDescending(x => x.Version) 
         .First()); 

爲亨裏克注意到這樣只會讓你一個項目 - 我沒有看到獲得更多,因爲原因該項目只seemd解釋包括兩個領域,但是這很容易handeled - 添加另一組的版本:

var result = 
    list.GroupBy(x => x.Number) 
     .Select(gr => 
        gr.GroupBy(x => x.Version) 
         .OrderByDescending(gr2 => gr2.Key) 
         .Select(gr => gr.ToArray())); 

這將導致與最大版本陣列的枚舉 - 但是我無法測試所以可能會有語法或語義錯誤,但縮進應該清楚,錯誤容易刪除。

+0

謝謝,這是完美的工作。 :D –

+0

注意問題中的複數形式:「我想選擇組中具有最高版本的所有項目」。該解決方案僅選擇每個組中的一個項目。 – Henrik

+0

Henrik:對,邁克爾似乎很好,但我會添加另一個處理此問題的人 – Carsten

0

只要刪除&& b != a部分。

+0

這將只返回整個列表,因爲每個元素都將與自身進行比較,對於每個元素,「a.Version」總是'> ='。 –

+0

@邁克爾 - 再想一想。刪除'&& b!= a'只能增加最大值。 – Henrik

2

像你想通過數字組,然後再通過版本排序,並採取最後一項聽起來對我說:

var result = from entry in list 
      group entry by entry.Number into g 
      select g.OrderBy(x => x.Version).Last(); 

或避免實際訂貨,如果你不介意創建新條目:

var result = from entry in list 
      group entry by entry.Number into g 
      select new Entry { Number = g.Key, 
           Version = g.Max(x => x.Version) }; 

編輯:使用OrderByDescending,而不是按卡斯滕的做法避免了迭代到最後一個條目:

var result = from entry in list 
      group entry by entry.Number into g 
      select g.OrderByDescending(x => x.Version).First(); 
0

是否這樣?

var result = from e in elements 
      group e by e.Number into eGroup 
      select eGroup.OrderByDescending(x => x.Version).First(); 
相關問題