2013-04-07 76 views
7

我有一個集合,例如:在LINQ Lambda表達式使用的GroupBy和最大

**id1, id2, value** 
    1 9 12 
    2 9  6 
    3 11 8 
    4 11 87 

我想使用LINQ和得到以下結果:

**value** 
    6 
    87 

附:

id1 - select MAX; 
id2 - group column; 

我需要的

var result = list.GroupBy(x=>x.id2).select(s=>s.value); 

我希望你的幫助形式的答案。

+0

您還沒有表達清楚你的問題在所有。 *爲什麼*你會期望結果是6和87?爲什麼當每行有不同的id1時,通過id1進行分組?如果你用id2進行分組會更有意義,但結果應該是12和87,而不是6和87.請花一些時間讓你的問題清楚。 – 2013-04-07 18:28:40

+0

但是'6 <12'和'87> 8';請解釋。 – 2013-04-07 18:28:59

+0

我想他希望按id2分組,並從每個組中選擇最大值 – 2013-04-07 18:30:31

回答

23

編輯:好的,現在我們已經有了一個清晰的略微組需求(雖然還遠未明確的書面)最簡單的方法很可能是:

var maxes = list.GroupBy(x => x.id2, 
         (key, xs) => xs.OrderByDescending(x => x.id1) 
             .First() 
             .value); 

不幸的是LINQ並沒有提供一個簡單的方法獲得「具有最大值的元素」(而不是最大值本身)。我在MoreLINQ的方法,它做到這一點,雖然,叫MaxBy

var maxes = list.GroupBy(x => x.id2, 
         (key, xs) => xs.MaxBy(x => x.id2).value); 

原來的答覆(由ID2分組,取最大值)

我回答假設你實際上意味着按id2而不是id1進行分組,您實際上想要12和87的結果而不是6和87.在這種情況下,您希望:

var maxes = list.GroupBy(x => x.id2, (id, xs) => xs.Max(x => x.value)); 

或(可能更容易理解):

var maxes = list.GroupBy(x => x.id2) 
       .Select(xs => xs.Max(x => x.value)); 

或者:

var maxes = list.GroupBy(x => x.id2, x => x.value) 
       .Select(values => values.Max()); 

或者:

var maxes = list.GroupBy(x => x.id2,  // Key selector 
         x => x.value, // Element selector 
         (key, values) => values.Max()); // Result selector 

甚至:

var maxes = list.GroupBy(x => x.id2) 
       .Select(xs => xs.Select(x => x.value).Max()); 

正如你所看到的,GroupBy有很多重載:)

或者你可以使用查詢表達式:

var maxes = from x in list 
      group x.value by x.id2 into values 
      select values.Max(); 

你不應該限制自己要麼查詢表達式或擴展方法版本 - 理解這兩者很重要,所以你可以使用任何最合適的。

+0

id1 - 選擇MAX; id2 - 組列; – Pavel 2013-04-07 18:46:52

+0

感謝您的回覆,但我必須爲每個id2選擇VALUE,其中id1 - MAX – Pavel 2013-04-07 19:11:03

+0

@PavelIvanov:好吧,我*想*我明白您的意思,但您應該在將來更加明確地做出明確表示。看到我的編輯有希望解決這個問題的答案... – 2013-04-08 05:45:41

4

顯然OP希望Value最大Id1Id2

的樣本數據:

public class Row 
{ 
    public int Id1; 
    public int Id2; 
    public int Value; 
} 

List<Row> rows = new List<Row>(){ 
    new Row(){Id1=1,Id2=9,Value=12}, 
    new Row(){Id1=2,Id2=9,Value=6}, 
    new Row(){Id1=3,Id2=11,Value=8}, 
    new Row(){Id1=4,Id2=11,Value=87} 
}; 

解決方案:

List<int> res = rows.GroupBy(r => r.Id2) 
        .Select(g => g.OrderByDescending(i=>i.Id1).First().Value) 
        .ToList(); 
0

在情況下,它可以幫助別人,我也有類似的情況除外需要返回多個記錄而不是單個記錄。

例如,

**id1, id2, value** 
    1 9 12 
    2 9  6 <- 
    2 9  7 <- 
    3 11 8 
    4 11 87 <- 
    4 11 88 <- 

下返回上面的四個記錄爲兩個記錄兩個列表(枚舉可枚舉的):

var maxes = from x in list 
      group x by x.id2 into xs 
      select new {values = xs.Where(x => x.id1 == xs.Max(y => y.id1))}; 

var maxes = list.GroupBy(x => x.id2, 
      (key, xs) => new 
      { 
       values = xs.Where(x => x.id1 == xs.Max(y => y.id1)) 
      });