【问题标题】:Using GroupBy and Max in LINQ Lambda Expressions在 LINQ Lambda 表达式中使用 GroupBy 和 Max
【发布时间】:2013-03-29 18:24:12
【问题描述】:

我有一个收藏,例如:

**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);

希望对你有所帮助。

【问题讨论】:

  • 你的问题根本没有表达清楚。 为什么你会期望结果是 6 和 87?当每一行都有不同的 id1 时,为什么要按 id1 分组?如果您按 id2 分组会更有意义,但结果应该是 12 和 87,而不是 6 和 87。请花一些时间来明确您的问题。
  • 但是6 < 1287 > 8;请解释一下。
  • 我想他想按 id2 分组并从每个组中选择 Max Value
  • @anouar.bag:这也是我的怀疑,但如果是这样,这个问题写得非常粗心。
  • 你的预期结果应该是 12 和 87 吗?

标签: linq select lambda group-by max


【解决方案1】:

编辑:好的,现在我们有了更清晰的一组要求(尽管还远未写清楚),最简单的方法可能是:

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();

您不应限制自己查询表达式或扩展方法版本 - 了解两者很重要,因此您可以使用最合适的任何内容。

【讨论】:

  • id1 - 选择 MAX; id2 - 组列;
  • 感谢您的回复,但我必须为每个 id2 选择 V​​ALUE,其中 id1 - MAX
  • @PavelIvanov:好的,我认为我明白你的意思,但你真的应该在未来更加努力地明确这一点。请参阅我的编辑以获取希望解决此问题的答案...
  • 我不得不将第一个 sn-p 中的 First() 调用更改为 FirstOrDefault()。实体框架为 First() 抛出 NotSupportedException。
【解决方案2】:

显然 OP 想要 ValueId2 内最大 Id1

样本数据:

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();

【讨论】:

    【解决方案3】:

    如果它对其他人有帮助,我遇到了类似的情况,除了需要返回多条记录而不是一条记录。

    例如。

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

    下面将上述四条记录作为两个记录的两个列表(enumerable of enumerables)返回:

     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))
                });
    

    【讨论】:

      猜你喜欢
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-10
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      相关资源
      最近更新 更多