LINQ Aggregate function up to current row

c#, linq

Solution

The easiest way to do this is to use the Microsoft Reactive Extension Team's "Interactive Extension" method `Scan`. (Use NuGet and look for `Ix-Main`.)

var query =
    list
        .Scan(new
        {
            Price = 0,
            IsFirst = true,
            First = 0,
            Second = 0,
            Final = 0
        }, (a, x) => new
        {
            Price = x.Price,
            IsFirst = x.IsFirst,
            First = x.IsFirst ? x.Price : 0,
            Second = !x.IsFirst ? x.Price : 0,
            Final = a.Final + (x.IsFirst ? x.Price : - x.Price)
        });

This gives:

However, you can do it with the built-in `Aggregate` operator like this:

var query =
    list
        .Aggregate(new []
        {
            new
                {
                    Price = 0,
                    IsFirst = true,
                    First = 0,
                    Second = 0,
                    Final = 0
                }
        }.ToList(), (a, x) =>
        {
            a.Add(new
            {
                Price = x.Price,
                IsFirst = x.IsFirst,
                First = x.IsFirst ? x.Price : 0,
                Second = !x.IsFirst ? x.Price : 0,
                Final = a.Last().Final + (x.IsFirst ? x.Price : - x.Price)
            });
            return a;
        })
        .Skip(1);

You get the same result.

Problem

Assuming I have the following ``` var list = new []{ new { Price = 1000, IsFirst = true}, new { Price = 1100, IsFirst = false}, new { Price = 450, IsFirst = true}, new { Price = 300, IsFirst = false} }; ``` and I want to generate the following output: ``` Price IsFirst First Second Final ---------------------------------- 1000 True 1000 0 1000 1100 False 0 1100 -100 450 True 450 0 350 300 False 0 300 50 ``` Is it possible to have some sort of aggregate function processed up to current row? I like to have all the stuff in pure LINQ but as of now I have no other choice than manually iterating the list and sum the column conditionally. ``` var result = list.Select(x => new { Price = x.Price, IsFirst = x.IsFirst, First = x.IsFirst ? x.Price : 0, Second = !x.IsFirst ? x.Price : 0, Final = 0 // ??? }).ToList(); int sum = 0; for(int i=0; i<result.Count(); i++) { sum += (result[i].IsFirst ? result[i].Price : - result[i].Price); // updating Final value manually } ```

Original source

Related problems