LINQ - 按条件分组,然后有条件地求和
LINQ - 按条件分组,然后有条件地求和
我有一个数据集(汽车):\n
品牌 销售日期 金额 购买/销售 丰田 06/07/2015 18.5 购买 宝马 01/01/2016 25.15 销售 奔驰 06/06/2016 20.75 购买
\n我想按年份分组,并返回金额的总和,即:\n
年份 金额 2015 -18.5 2016 4.4
\n并将其输出到列表框中。\n我可以对金额进行求和,不考虑购买/销售条件:\n
var AmountsByYear = cars.GroupBy(i => i.Date.Year) .Select(g => new { 年份 = g.Key, 总金额 = g.Sum(i => i.金额) }).ToList(); lstAmountsByYear.DataSource = AmountsByYear;
问题出现的原因是需要对一组汽车按照年份进行分组,并根据购买或销售情况计算出总金额。解决方法是创建一个扩展方法,将汽车的购买或销售情况转换为正数或负数的金额值,并使用正确的Enumerable.GroupBy重载方法对汽车按年份进行分组,然后使用Sum方法计算总金额。
以下是完整的文章:
考虑创建一个Car的扩展方法,将[Amount, bought/sold]的组合转换为Amount的正数或负数值:
public static decimal ToProperAmountValue(this Car car) { return car.IsCarBought ? -car.Amount : car.Amount; } // TODO: invent proper method name
此外,使用正确的Enumerable.GroupBy重载方法来自动执行Select操作:
var amountsByYear = cars.GroupBy( // KeySelector: 将汽车按年份分组 car => car.Date.Year) // ResultSelector: 使用Key和具有相同Key的汽车创建一个新对象 (year, carsInThisYear => new { Year = year, Total = carsInThisYear.Sum(car => car.ToProperAmountValue()) }) .ToList();
以上代码中,ToProperAmountValue方法用于将汽车的Amount根据IsCarBought属性转换为正数或负数。GroupBy方法按照汽车的年份进行分组,并使用Sum方法计算每个分组中汽车的总金额。最后,使用ResultSelector将年份和总金额组合成一个新的对象,并将结果存储在amountsByYear列表中。
通过这种方法,我们可以方便地按年份对汽车进行分组,并根据购买或销售情况计算出总金额。这样的代码结构更加清晰和易于理解。
问题的原因是需要对数据进行分组并按条件求和。在给出的示例中,"Bought/Sold"字段的定义不明确,建议使用枚举来定义该字段。然后,可以使用LINQ中的GroupBy和Sum方法来实现分组和条件求和的操作。
解决方法如下:
1. 首先,定义一个Car类和一个BusinessType枚举,用于表示汽车的品牌、日期、金额和业务类型。
public class Car { public string Brand; public DateTime Date; public double Amount; public BusinessType BusinessType; } public enum BusinessType { Bought = -1, Sold = 1 }
2. 在输入数据中创建一个Car对象的列表,用于存储汽车的信息。
var cars = new List{ new Car{Brand="Toyota", Date = new DateTime(2015,06,07),Amount=18.5,BusinessType=BusinessType.Bought}, new Car{Brand="BMW", Date = new DateTime(2016,01,01),Amount=25.15,BusinessType=BusinessType.Sold}, new Car{Brand="Mercedes", Date = new DateTime(2016,06,06),Amount=20.75,BusinessType=BusinessType.Bought}, };
3. 使用LINQ的GroupBy方法按照日期的年份对汽车进行分组,并使用Sum方法根据业务类型求和。在求和的过程中,通过将业务类型转换为整数来实现条件求和。
var AmountsByYear = cars.GroupBy(i => i.Date.Year) .Select(g => new { Year = g.Key, Total = g.Sum(i => i.Amount*(int)i.BusinessType) }).ToList();
4. 最后,将结果输出,以图表的形式展示每年的总金额。
输出结果如下所示:
以上就是解决该问题的步骤和方法。使用LINQ的GroupBy和Sum方法,可以方便地对数据进行分组和条件求和的操作。通过将业务类型转换为整数,可以根据条件对金额进行求和。最终的输出结果可以清晰地展示每年的总金额。