Linq 使用 group by 获取总计

Linq Get totals using group by

我有以下 class:

class Item
{
    public decimal TransactionValue { get; set; }
    public string TransactionType { get; set; }
}

我有这个列表:

        var items = new List<Item>
        {
            new Item
            {
                TransactionValue = 10,
                TransactionType = "Income"
            },
            new Item
            {
                TransactionValue = 10,
                TransactionType = "Income"
            },
            new Item
            {
                TransactionValue = -5,
                TransactionType = "Outgoing"
            },
            new Item
            {
                TransactionValue = -20,
                TransactionType = "Outgoing"
            }
        };

我正在尝试根据 ValueType 获取总和,我尝试了下面的方法,但它添加了所有内容并给我一个总计,即 -5,我想要的是每种交易类型的总计,所以我想得到一个新的 class,即下面的总计 class,并使用以下数据:TotalIncoming : 20 和 TotalOutgoing : - 25.

        var r = items.Sum(x => x.TransactionValue);

class Totals
{
    public decimal TotalIncoming { get; set; }
    public decimal TotalOutgoing { get; set; }
}

谢谢

我确信可能有一种聪明的方法可以使用 Linq 在一行中完成此操作,但我能想到的一切都很丑陋,所以我选择了一些更具可读性的东西。

var results = items.GroupBy(x => x.TransactionType)
    .ToDictionary(x => x.Key, x => x.Sum(y => y.TransactionValue));

var totals = new Totals
{
    TotalIncoming = results["Income"],
    TotalOutgoing = results["Outgoing"]
};

您可以通过以下查询获得您想要的结果:-

Totals result = new Totals
     {
        TotalIncoming = items.Where(x => x.TransactionType == "Income")
                             .Sum(x => x.TransactionValue),
        TotalOutgoing = items.Where(x => x.TransactionType == "Outgoing")
                             .Sum(x => x.TransactionValue)
     };

但是,正如您在类型 Totals 中看到的那样,我们需要对 TransactionType 进行硬编码,并且除了所使用的命名约定之外,我们无法从结果中得知此 Sum 属于哪种类型。

我将改为创建以下类型:-

class ItemTotals
{
   public string ItemType { get; set; }
   public decimal Total { get; set; }
}

这里我们将在结果中包含 TransactionType 及其相应的总计,我们可以简单地按 TransactionType 分组并计算总和,这里是相同的查询:-

List<ItemTotals> query = items.GroupBy(x => x.TransactionType)
                                          .Select(x => new ItemTotals
                                          {
                                              ItemType = x.Key,
                                              Total = x.Sum(z => z.TransactionValue)
                                          }).ToList();

这是完整的Working Fiddle,您可以从两者中选择。