tags:

views:

83

answers:

1

I'm trying to get the running total by using extension. And it is working now.

    public static IEnumerable<TResult> Rollup<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        TResult seed,
        Func<TSource, TResult, TResult> projection)
    {
        if (!source.Any())
        {
            yield break;
        }

        TSource[] ordered = source.OrderBy(keySelector).ToArray();
        TKey previous = keySelector(ordered[0]);

        TResult nextSeed = seed;
        foreach (TSource src in source)
        {
            TKey current = keySelector(src);
            if (!current.Equals(previous))
            {
                nextSeed = seed;
            }
            TResult projectedValue = projection(src, nextSeed);
            nextSeed = projectedValue;
            yield return projectedValue;

            previous = current;
        }
    }  

public class Items {
    public string Item { get; set; }
    public int Qty { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        List<Items> myList = new List<Items>();
        myList.Add(new Items { Item = "A", Qty = 3 });
        myList.Add(new Items { Item = "A", Qty = 12 });
        myList.Add(new Items { Item = "B", Qty = 4 });
        myList.Add(new Items { Item = "B", Qty = 5 });
        myList.Add(new Items { Item = "A", Qty = 6 });
        myList.Add(new Items { Item = "A", Qty = 8 });
        myList.Add(new Items { Item = "B", Qty = 20 });

        var total = myList.OrderBy(x => x.Item).Rollup(x => x.Item, 0, (s, y) => s.Qty + y);
        foreach (var i in total)
        {
            Console.WriteLine(i);
        }

        Console.ReadLine();       

    }
}

Output    :
    3
    15
    21
    29
    4
    9
    29

I want to get the sorted sequence at the same time. Something like bellow

  Seq   Running Total
    1   3
    2   15
    3   21
    4   29
    1   4
    2   9
    3   29

Anyone has a good solution to return the sequence and running total at the sametime using above Linq extension(Rollup)?

+2  A: 

This should work:

public class OrderSumPair<TResult>
{
    public int Order { get; set;}
    public TResult Value { get; set; }
}

public static IEnumerable<OrderSumPair<TResult>> Rollup<TSource, TKey, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    TResult seed,
    Func<TSource, TResult, TResult> projection)
    {
        if (!source.Any())
        {
            yield break;
        }

        TSource[] ordered = source.OrderBy(keySelector).ToArray();
        TKey previous = keySelector(ordered[0]);
        int count = 1;

        TResult nextSeed = seed;
        foreach (TSource src in source)
        {
            TKey current = keySelector(src);
            if (!current.Equals(previous))
            {
                nextSeed = seed;
                count = 1;
            }
            TResult projectedValue = projection(src, nextSeed);
            nextSeed = projectedValue;
            yield return new OrderSumPair<TResult> { Order = count, Value = projectedValue };

            previous = current;
            count++;
        }
    }

And your write loop:

    foreach (var i in total)
    {
        Console.WriteLine(i.Order + " " + i.Value);
    }
Euphoric
Great! It works now. Thank you Euphoric!
Michael