【问题标题】:Cumulative sum in list of objects with lambda expressions C#具有 lambda 表达式 C# 的对象列表中的累积和
【发布时间】:2018-03-01 01:19:18
【问题描述】:

我需要使用 lambda 表达式在列表中显示累积和。你知道我该怎么做吗? 我有这个回报:

[
{
    "dt_created": "2018-02-25",
    "qtNewItens": 1
},
{
    "dt_created": "2018-02-26",
    "qtNewItens": 1
},
{
    "dt_created": "2018-02-27",
    "qtNewItens": 2
}

]

但我必须显示这个:

[
{
    "dt_created": "2018-02-25",
    "qtNewItens": 1
},
{
    "dt_created": "2018-02-26",
    "qtNewItens": 2
},
{
    "dt_created": "2018-02-27",
    "qtNewItens": 4
}

]

我不知道是否可以使用 GroupBy 或 Aggregate

我尝试了这样的方法,但它是错误的:

var newItensByDay = ctx.Itens
                    .GroupBy(x => new { Data = x.dt_created, x.Id })
                    .Select(g => new {
                        Qt = g.Select(x => x.Id).Count(),
                        Dt_created = g.Select(x => x.dt_created).FirstOrDefault()
                    })
                    .GroupBy(x => new { x.Qt, x.Dt_created })
                    .Select(grp => new {
                        dt_created = grp.Key.Dt_created,
                        qtNewItens = grp.Sum(x => x.Qt)
                    });

【问题讨论】:

  • 输出是否应该有 TotalItemsToDate 字段而不是 NewItems 字段?
  • 您是否按 dt_created 进行分组,因为它们可能不是唯一的(并且按顺序)?

标签: c# lambda sum aggregate


【解决方案1】:

分组后考虑下面的累积选择

var itemsByDay = ctx.Itens
                    .GroupBy(x => x.dt_created)
                    .Select(g => new {
                        Qt = g.Count(),
                        Dt_created = g.Key
                    });

var count = 0;
var cumulativeByDay = itemsByDay.Select(x => {
    count += x.Qt;
    var result = new {
        dt_created = x.Dt_created,
        qtNewItens = count
    };
    return result;
});

【讨论】:

    【解决方案2】:

    这应该做你想做的:

    var runningTotal = 0;
    dataList.Select(x=>new Data(){dt_created = x.dt_created, qtNewItems = (runningTotal+=x.qtNewItems)}).Dump();
    

    本质上,它定义了一个变量用作 runningTotal,然后在投影中它使用 runningTotal+=x.qtNewItems 将值添加到运行总计,然后将其分配给新对象。

    【讨论】:

      【解决方案3】:

      如果您希望客户端代码成为一个表达式,您可以创建一个通用 AccumulatingSelect 迭代器并像这样使用它:

      source.AccumulatingSelect (
          0, 
          (s, a) => s.qtNewItens + a, 
          (s, a) => new { s.dt_created, TotalToDate = a })
      

      .

      public static class Extensions {
          public static IEnumerable<V> AccumulatingSelect<T, U, V>(
            this IEnumerable<T> source, 
            U seed, 
            Func<T, U, U> accumulator, 
            Func<T, U, V> projector)
          {
              U acc = seed;
              foreach (var value in source)
              {
                  acc = accumulator(value, acc);
                  yield return projector(value, acc);
              }
          }
      }
      

      这是@Chris gave 的过度修饰版本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-02
        • 1970-01-01
        • 2018-09-02
        • 1970-01-01
        相关资源
        最近更新 更多