I have a sequence of numbers:
var seq = new List<int> { 1, 3, 12, 19, 33 };
and I want to transform that into a new sequence where the number is added to the preceding numbers to create a new sequence:
{ 1, 3, 12, 19, 33 } --> {1, 4, 16, 35, 68 }
I came up with the following, but I dislike the state variable 'count'. I also dislike the fact that I'm using the values Enumerable without acting on it.
int count = 1;
var summed = values.Select(_ => values.Take(count++).Sum());
How else could it be done?
To use Linq and only iterate over the list once you could use a custom aggregator:
..
Just to offer another alternative, albeit not really LINQ, you could write a yield-based function to do the aggregation:
Like BrokenGlass's this makes only a single pass over the data although unlike his returns an iterator not a list.
(Annoyingly you can't easily make this generic on the numeric type in the list.)
"Pure" LINQ:
var result = seq.Select((a, i) => seq.Take(i + 1).Sum());
One more "pure" LINQ O(n):
One more LINQ, with state maintenance:
This is a common pattern in functional programming which in F# is called scan. It's like C#'s Enumerable.Aggregate and F#'s fold except that it yields the intermediate results of the accumulator along with the final result. We can implement scan in C# nicely with an extension method:
And then use it as follows:
Stephen Swensen's answer is great, scan is exactly what you need. There is another version of scan though that doesn't require a seed, which would be slightly more appropriate for your exact problem.
This version requires that your output element type is the same as your input element type, which it is in your case, and gives the advantage of not needing you to pass in a 0 and then Skip the first (0) result.
You can implement this version of scan in C# as follows:
And then use it as follows: