2013-04-07 46 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)) 
      });