Introduction
This is a fully generic implementation of the tip described by Mika Wendelius.
Using the Code
The simple extension method which handles a simple accumulation (like the CumulativeSum
of the original tip) is this:
public static IEnumerable<Titems> CumulativeSequence<Titems>
(this IEnumerable<Titems> sequence,
Func<Titems, Titems, Titems> accumulateOperation)
{
return CumulativeSequence(sequence, default(Titems), accumulateOperation, a => a);
}
This clearly just defers to a fully parameterized implementation (which is necessary to implement the CumulativePath
functionality of the original tip):
public static IEnumerable<Tvalues> CumulativeSequence<Titems, Taccum,
Tvalues>(this IEnumerable<Titems> sequence,
Taccum accumulatorInitializer,
Func<Taccum, Titems, Taccum> accumulateOperation,
Func<Taccum, Tvalues> valueOperation)
{
Taccum accumulator = accumulatorInitializer;
return sequence.Select(item => {
accumulator = accumulateOperation(accumulator, item);
return valueOperation(accumulator);
});
}
(using
statements are omitted, see the attached code file.)
Here is the usage corresponding to the CumulativeSum
(these give the same output as the original tip):
private static decimal Sum(decimal a, decimal b) { return a + b; }
static void Main()
{
decimal[] numbers = new decimal[] { 1, 3, 5, 7, 11 };
foreach (decimal partialSum in numbers.CumulativeSequence((a, n) => a + n))
{
Debug.Print(" - {0}", partialSum);
}
Debug.Print("The cumulative sum total is {0}", numbers.CumulativeSequence(Sum).Last());
The CumulativePath
of the original tip used a StringBuilder
for the path accumulation, and is implemented like this:
var splitPath = @"C:\Some directory\Some subdirectory\Somefile.txt".Split('\\');
Debug.Print("The path contains the following parts");
var pathSequence = splitPath.CumulativeSequence(new StringBuilder(),
(a, p) => {
if (a.Length != 0)
a.Append('\\');
a.Append(p);
return a;
},
a => a.ToString());
foreach (string partialPath in pathSequence)
{
Debug.Print(" - '{0}'", partialPath);
}
}
History
- July 27, 2012 - Initial alternative
I started programming in Basic on a DECSystem-10 as a Freshman at Caltech in 1974. I quickly transitioned to assembly language, Fortran, and Pascal. As a summer job at JPL, I did analysis of fuel consumption for the Viking Mars Orbiter attitude control system. I also spent a summer doing O/S maintenance at Digital Equipment Corporation.
After graduation, I started developing microprocessor development tools (e.g., cross-compiler, debugger) for Beckman Instruments, a scientific instrument company.
I've worked on custom file-systems, a real-time O/S for Z8000, Expert Systems (SpinPro™ & PepPro™), and internal and external networking support (I was their first webmaster).
I've worked on the DNA analysis system.
I was the console/UI software architect for Ultracentrifuges and protein Capillary Electrophoresis (CE) systems.
After 35 years, Danaher having acquired Beckman (now Beckman Coulter), transferred the CE group to become part of Sciex (2014), and was on the software team that developed the new (9/2021) Sciex BioPhase Capillary Electrophoresis instrument.
---
Finally, after 43 years, 7 months, and 19 days, I am retired.