我使用以下函数来查找终端累计正负值,该函数正在工作:
public class CumulativeTotal
{
[Test]
public void CalculatesTerminalValue()
{
IEnumerable<decimal> sequence = new decimal[] { 10, 20, 20, -20, -50, 10 };
var values = FindTerminalValues(sequence);
Assert.That(values.Item1, Is.EqualTo(-20));
Assert.That(values.Item2, Is.EqualTo(50));
Assert.Pass();
}
public static Tuple<decimal,decimal> FindTerminalValues(IEnumerable<decimal> values)
{
decimal largest = 0;
decimal smallest = 0;
decimal current = 0;
foreach (var value in values)
{
current += value;
if (current > largest)
largest = current;
else if (current < smallest)
smallest = current;
}
return new Tuple<decimal, decimal>(smallest,largest);
}
}
然而,在学习的兴趣,我怎么能实现与Linq?
我可以看到一个包MoreLinq,但不确定从哪里开始!
4条答案
按热度按时间6xfqseft1#
您可以尝试标准Linq
Aggregate
方法:h7appiyu2#
是的,你可以这样使用MoreLinq,它有Scan方法。
Scan扩展方法通过将函数应用于输入序列中的每个元素,并使用前一个元素作为累加器来生成新序列。在这种情况下,函数只是加法运算符,因此Scan方法生成输入序列的累加和序列。
umuewwlo3#
你所展示的代码的主要缺陷是,如果序列的运行总和一直小于零或大于零,那么算法会错误地将零作为一个终端返回。
拿着这个
当前算法返回
(0, 30)
,而实际上它应该是(10, 30)
。要更正此问题,必须从序列的第一个值开始,将其作为默认的最小值和最大值。
下面是一个实现:
它使用
System.Interactive
来获取Scan
运算符(但您也可以使用MoreLinq
。但是,这种方法的缺点是
IEnumerable<decimal>
不能保证每次都返回相同的值,您要么需要(1)传入decimal[]
、List<decimal>
或其他总是返回相同序列的结构,要么(2)确保只迭代IEnumerable<decimal>
一次。下面是如何做(2):
lstz6jyr4#
您可以使用LINQ中的Aggregate方法来实现这一点。Aggregate方法将函数应用于序列中的每个元素并返回累加结果。它将初始累加器对象作为参数来跟踪最小和最大函数。