我正在尝试根据以下要求找到更好的处理数字序列的方法:
sequence[i]
的值是其自身值加上sequence[0]
到sequence[i-1]
的累积之和。
例如: 如果序列是一个列表
List<double> list = new List<double> { 10.0, 20.0, 30.0, 40.0 };
输出结果应为
list[0] = 10.0
list[1] = 20.0 + 10.0
list[2] = 30.0 + 10.0 + 20.0
list[3] = 40.0 + 10.0 + 20.0 + 30.0
我知道使用多次迭代的蛮力方式,但我想知道必须有一些更好的解决方案(可能使用LINQ)。
答案 0 :(得分:6)
假设您有权访问LINQ:
using System.Linq;
List<int> numbers = new List<int> {10, 20, 30, 40};
List<int> runningTotals = new List<int>(numbers.Count);
numbers.Aggregate(0, (sum, value) => {
sum += value;
runningTotals.Add(sum);
return sum;
});
答案 1 :(得分:5)
我的版本是对注释中的内容进行修改并返回IEnumerable而不是List但ToList()将对其进行排序。
应该非常有效率。谁不喜欢使用yield return
? ; - )
public IEnumerable<double> GetCumulativeSequence (IEnumerable<double> input)
{
var runningTotal = 0.0;
foreach (double current in input)
{
runningTotal+=current;
yield return runningTotal;
}
}
void Main()
{
List<double> list = new List<double> { 10.0, 20.0, 30.0, 40.0 };
var foo = GetCumulativeSequence(list);
}
这样做的主要优点是它只对输入数组进行一次循环。如果你实际上没有使用所有返回的东西(即你只看前三个)那么它将不会计算其余的东西。在更长的名单等方面可能有用。对于像Chris Doggett这样的答案,可能会有同样的说法,但不是所有那些使用linq的人。
答案 2 :(得分:4)
使用相对未知的Select重载,可以看到索引:
var result = list.Select((val, index) => list.Take(index + 1).Sum())
答案 3 :(得分:2)
非LINQ版本,只是为了与众不同:
List<double> GetSums(List<double> values)
{
List<double> sums = new List<double>();
double total = 0;
foreach(double d in values)
{
total += d;
sums.Add(total);
}
return sums;
}
答案 4 :(得分:2)
这是另一种类似于其中一个帖子的方法,但这个帖子是自包含的:
// C#
Enumerable.Range(1, 100)
.Aggregate(new List<int>{0},
(acc, x) => { acc.Add(acc.Last() + x); return acc; })
.Dump(); // Dump using LINQPad; ans: 5050
如果我们切换到int64,并使用10,000,000作为上限,并读取最终累积结果,则代码在Corei5上执行大约450毫秒,最终输出为:
500000.05亿
顺便提一下,对于1,000,000的上限,执行时间约为40毫秒,因此将尺寸增加10会使时间增加10倍。
答案 5 :(得分:1)
我构建了一个基于APL扫描运算符的扩展方法(具有很多变体)的扩展方法(类似于Aggregate
本质上是APL reduce运算符的方式),它返回操作序列的中间结果:< / p>
public static IEnumerable<TResult> Scan<T, TResult>(this IEnumerable<T> src, TResult seed, Func<TResult, T, TResult> combine) {
foreach (var s in src) {
seed = combine(seed, s);
yield return seed;
}
}
然后可以使用:
var ans = list.Scan(0.0, (a, d) => a+d).ToList();