Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq TakeWhile depending on sum (or aggregate) of elements

Tags:

c#

linq

aggregate

I have a list of elements and want to takeWhile the sum (or any aggregation of the elements) satisfy a certain condition. The following code does the job, but i am pretty sure this is not an unusual problem for which a proper pattern should exist.

var list = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
int tmp = 0;
var listWithSum = from x in list
                  let sum = tmp+=x
                  select new {x, sum};
int MAX = 10;
var result = from x in listWithSum
             where x.sum < MAX
             select x.x;

Does somebody know how to solve the task in nicer way, probably combining TakeWhile and Aggregate into one query?

Thx

like image 839
Martin Booka Weser Avatar asked Nov 05 '22 14:11

Martin Booka Weser


1 Answers

It seems to me that you want something like the Scan method from Reactive Extensions (the System.Interactive part) - it's like Aggregate, but yields a sequence instead of a single result. You could then do:

var listWithSum = list.Scan(new { Value = 0, Sum = 0 },
         (current, next) => new { Value = next,
                                  Sum = current.Sum + next });

var result = listWithSum.TakeWhile(x => x.Sum < MaxTotal)
                        .Select(x => x.Value);

(MoreLINQ has a similar operator, btw - but currently it doesn't support the idea of the accumulator and input sequence not being the same type.)

like image 94
Jon Skeet Avatar answered Nov 14 '22 22:11

Jon Skeet