【问题标题】:LINQ - group by, then sum conditionallyLINQ - 分组,然后有条件地求和
【发布时间】:2019-02-17 10:37:24
【问题描述】:

我有一个数据集(汽车):

Brand     DateSold    Amount  Bought/Sold
Toyota    06/07/2015  18.5    Bought
BMW       01/01/2016  25.15   Sold
Mercedes  06/06/2016  20.75   Bought  

我想按年份分组并返回金额的总和,即:

Year Amount  
2015 -18.5   
2016 4.4

并将其输出到列表框中。

我可以在没有买入/卖出条件的情况下求和:

var AmountsByYear = cars.GroupBy(i => i.Date.Year)
                        .Select(g => new { 
                            Year = g.Key,
                            Total = g.Sum(i => i.Amount)
                        }).ToList();
lstAmountsByYear.DataSource = AmountsByYear;

【问题讨论】:

  • 使用 Sum 表达式中的条件,例如类似g.Sum(i => i.IsSold ? i.Amount : -i.Amount)
  • @IvanStoev - 这应该作为答案发布:)

标签: c# linq


【解决方案1】:

由于您没有详细说明如何在数据结构中定义“买/卖”字段,我建议您使用枚举。例如,

public class Car
{
    public string Brand;
    public DateTime Date;
    public double Amount;
    public BusinessType BusinessType;
}

public enum BusinessType
{
    Bought = -1,
    Sold = 1
}

这将使您能够以最小的更改使用您的查询,以获得预期的结果。

var AmountsByYear = cars.GroupBy(i => i.Date.Year)
                    .Select(g => new { 
                        Year = g.Key,
                        Total = g.Sum(i => i.Amount*(int)i.BusinessType)
                    }).ToList();

输入数据,

var cars = new List<Car>
{
    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},
};

输出

【讨论】:

    【解决方案2】:

    考虑创建 Car 的扩展方法,将 [Amount, bought/sold] 的组合转换为 Amount 的正值或负值:

    public static decimal ToProperAmountValue(this Car car)
    {
        return car.IsCarBought ? -car.Amount : car.Amount;
    }
    // TODO: invent proper method name
    

    此外,请使用已经为您执行 Select 的正确 overload of Enumerable.GroupBy:

    var amountsByYear = cars.GroupBy(
    
        // KeySelector: Group Cars into Groups of same year
        car => car.Date.Year)
    
        // ResultSelector: take the Key and the Cars with this Key to make a new object
        (year, carsInThisYear => new
        { 
            Year = year,
            Total = carsInThisYear.Sum(car => car.ToProperAmountValue())
        })
        .ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2021-05-13
      • 1970-01-01
      • 2018-07-30
      • 1970-01-01
      相关资源
      最近更新 更多