如何在Linq查询中计算一系列整数的运行总和?

Mar*_*scu 5 c# linq

我试图想出一个linq查询来转换IEnumerable<int>为另一个IEnumerable<int>,其中结果中的每个int是从初始列表到该位置的所有int的总和:

鉴于int[] a
我需要int[] b
Where b[0] = a[0], b[1] = a[0] + a[1], b[2] = a[0] + a[1] + a[2]等等

或者,上面的总和可以写成b[1] = b[0] + a[1], b[2] = b[1] + a[2]等等,但我不知道这会有什么帮助.

当然,我可以通过for循环执行此操作,但是我从查询中获取a []序列,并且我认为如果我继续查询而不是突然添加for那里它会更好看:)

Jon*_*eet 16

好吧,你可以很容易地做副作用,虽然它很icky ......

int sum = 0;
int[] b = a.Select(x => (sum += x)).ToArray();
Run Code Online (Sandbox Code Playgroud)

如果框架提供了一种"运行聚合"来封装它,那将是很好的,但它并不是我所知道的.


Cam*_*and 8

我刚才写了一个函数来做这个.它类似于Haskell的scanl函数.

public static IEnumerable<TResult> Scan<T, TResult>(
    this IEnumerable<T> source, 
    Func<T, T, TResult> combine)
{
    using (IEnumerator<T> data = source.GetEnumerator())
        if (data.MoveNext())
        {
            T first = data.Current;

            yield return first;

            while (data.MoveNext())
            {
                first = combine(first, data.Current);
                yield return first;
            }
        }
}

int[] b = a
    .Scan((running, current) => running + current)
    .ToArray();
Run Code Online (Sandbox Code Playgroud)

  • 您在`yield return first`时遇到问题,如果是T类型而不是TResult,则* first * (2认同)

Cur*_*ols 5

Skeet先生解决方案的替代方案:如果我们放弃了对linq查询的要求,并且更确切地说"转换IEnumerable<int>为另一个IEnumerable<int>",我们可以使用:

    static IEnumerable<int> Sum(IEnumerable<int> a)
    {
        int sum = 0;
        foreach (int i in a)
        {
            sum += i;
            yield return sum;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我们可以应用于无限系列:

    foreach (int i in Sum(MyMath.NaturalNumbers))
        Console.WriteLine(i);
Run Code Online (Sandbox Code Playgroud)

如果您不想一次创建整个数组,这也很有用.