Linq rollup with sequence id
I'm trying to ge开发者_高级运维t 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)?
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);
}
精彩评论