LINQ Group使用Lambda通过两个对象属性和SUM,AVG或忽略其他对象属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LINQ Group使用Lambda通过两个对象属性和SUM,AVG或忽略其他对象属性相关的知识,希望对你有一定的参考价值。

我有使用LINQ Lambda语法组合在一起的对象列表。

public class Candy
{
  public string Id {get; set;}
  public string Name {get; set;}
  public string Distributor {get; set;}
  public int Quantity {get; set;}
  public decimal UnitPrice {get; set;}
}

样本集合List<Candy>可能如下所示:

{ Id = "AF001", Name = "Atomic Fireball", Distributor = "Wonka Candy", Quantity = 100, UnitPrice = 1 }
{ Id = "AF001", Name = "Atomic Fireball", Distributor = "Slugworth Confections", Quantity = 300, UnitPrice = 2 }
{ Id = "GW001", Name = "Gummy Worm", Distributor = "Wonka Candy", Quantity = 200, UnitPrice = 2 }
{ Id = "GW001", Name = "Gummy Worm", Distributor = "Slugworth Confections", Quantity = 250, UnitPrice = 3 }
{ Id = "CG001", Name = "Cherry Gumball", Distributor = "Wonka Candy", Quantity = 30000, UnitPrice = 3 }
{ Id = "GF001", Name = "Grape Fizzy", Distributor = "Slugworth Confections", Quantity = 30000, UnitPrice = 1 }

我想使用LINQ Lambda对具有相同Id和Name的项进行分组。对于那些分组的项目,我想要数量和平均价格。我想最终得到一个看起来像这样的分组。

{ Id = "AF001", Name = "Atomic Fireball", Distributor = "Wonka Candy", Quantity = 400, UnitPrice = 1.5 }
{ Id = "GW001", Name = "Gummy Worm", Distributor = "Wonka Candy", Quantity = 450, UnitPrice = 2.5 }
{ Id = "CG001", Name = "Cherry Gumball", Distributor = "Wonka Candy", Quantity = 30000, UnitPrice = 3 }
{ Id = "GF001", Name = "Grape Fizzy", Distributor = "Slugworth Confections", Quantity = 30000, UnitPrice = 1 }

我在想这样的事情,但我不确定如何在LINQ中使用聚合函数。

List<Candy> ungroupedCandies = GetCandies();

List<Candy> groupedCandies = ungroupedCandies.GroupBy(
                                               c => c.Id,
                                               c => c.Name)
                                              .Select(NOT SURE HERE)

我真的很想坚持使用Lambda语法而不是查询表达式。

答案
  • 按多个字段分组需要new匿名类型,
  • 获得组后,选择带有计算字段的新Candy对象,
  • 平均单价仅在所有数量相同时才有效。您需要计算总价格,并将其除以总数量以查找平均价格。

以下是如何做到这一点:

var grouped = ungroupedCandies
    .GroupBy(c => new {c.Id, c.Name })
    .Select(g => new Candy {
        Id = g.Key.Id
    ,   Name = g.Key.Name
    ,   Distributor = g.First().Distributor
    ,   Quantity = g.Sum(c => c.Quantity)
    ,   UnitPrice = g.Sum(c => c.Quantity * c.UnitPrice) / g.Sum(c => c.Quantity)
    })
    .ToList();

注意:要了解为什么直接平均不起作用,请考虑与{Q=1, P=1}{Q=999, P=2}相同的两组糖果。 1000个糖果的平均价格将非常接近2,因为来自第一组的单个“半价”糖果不会对1000个糖果的总体数量产生影响。

以上是关于LINQ Group使用Lambda通过两个对象属性和SUM,AVG或忽略其他对象属性的主要内容,如果未能解决你的问题,请参考以下文章

帮助将 SQL 语句转换为 LINQ Lambda(在 group by 和 sum 方面需要帮助)

使用 Linq.Expression 访问具有动态 lambda 的嵌套属性

内部在LINQ Lambda中使用两个相等的内部连接

如何使用linq / lambda计算具有唯一属性的列表中的对象数?

如何通过 Lambda 或 LINQ 从列表中获取不同的实例

LINQ 以 Lambda 形式选择不同计数