Linq汇总与序列ID

时间:2010-10-04 02:51:28

标签: c# linq

我正在尝试使用扩展程序来获取运行总计。它现在正在运作。

    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

我想同时获得排序序列。像贝洛一样的东西

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

任何人都有一个很好的解决方案,可以使用上面的Linq扩展(Rollup)同时返回序列并运行总计?

1 个答案:

答案 0 :(得分:3)

这应该有效:

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++;
        }
    }

你的写循环:

    foreach (var i in total)
    {
        Console.WriteLine(i.Order + " " + i.Value);
    }