# 使用Linq来总结一个数字（并跳过其余的）

``class Person { public string Name {get; set;} public int Amount {get; set;} }` `

` `IList<Person> people;` `

` ` var subgroup = new List<Person>(); people.OrderByDescending(x => x.Amount); var count = 0; foreach (var person in people) { count += person.Amount; if (count < requestedAmount) { subgroup.Add(person); } else { break; } }` `

## UPDATE

` `var count = 0; var subgroup = people .OrderByDescending(x => x.Amount) .TakeWhile(x => (count += x.Amount) < requestedAmount) .ToList();` `

` `int s = 0; var subgroup = people.OrderBy(x => x.Amount) .TakeWhile(x => (s += x.Amount) < 1000) .ToList();` `

` `.TakeWhile(x => { bool bExceeds = s > 1000; s += x.Amount; return !bExceeds; })` `

`TakeWhile`在这里检查了一次迭代的`s`值，所以需要再多一次，以确保已经超过了`1000`

LINQ没有正在运行的聚合是一件令人遗憾的事情。 我build议在这篇文章中user2088029的代码： 如何计算Linq查询中的一系列整数的运行总和？ 。

` `var y = people.Scanl(new { item = (Person) null, Amount = 0 }, (sofar, next) => new { item = next, Amount = sofar.Amount + next.Amount } );` `

` `public static IEnumerable<TResult> Scanl<T, TResult>( this IEnumerable<T> source, TResult first, Func<TResult, T, TResult> combine) { using (IEnumerator<T> data = source.GetEnumerator()) { yield return first; while (data.MoveNext()) { first = combine(first, data.Current); yield return first; } } }` `

` `people [{"a", 100}, {"b", 200}, ... ]` `

` `people.Aggregate((sofar, next) => new {item = next, total = sofar.total + next.value}) [{item: {"a", 100}, total: 100}, {item: {"b", 200}, total: 300}, ... ]` `

` `people .Aggregate((sofar, next) => new {item = next, total = sofar.total + next.value}) .TakeWhile(x=>x.total<1000) .Select(x=>x.Item)` `

` `public static IEnumerable<T> AggregatingTakeWhile<T, U>( this IEnumerable<T> items, U first, Func<T, U, U> aggregator, Func<T, U, bool> predicate) { U aggregate = first; foreach (var item in items) { aggregate = aggregator(item, aggregate); if (!predicate(item, aggregate)) yield break; yield return item; } }` `

` `var subgroup = people .OrderByDescending(x => x.Amount) .AggregatingTakeWhile( 0, (item, count) => count + item.Amount, (item, count) => count < requestedAmount) .ToList();` `

` `int sumCount = 0; var subgroup = people .OrderByDescending(item => item.Amount) // <-- you wanted to sort them? .Where(item => (sumCount += item.Amount) < requestedAmount) .ToList();` `

` `public static IEnumerable<T> TakeWhileAdding<T>( this IEnumerable<T> source, Func<T, int> selector, Func<int, bool> comparer) { int total = 0; foreach (var item in source) { total += selector(item); if (!comparer(total)) yield break; yield return item; } }` `

` `var values = new Person[] { new Person { Name = "Name1", Amount = 300 }, new Person { Name = "Name2", Amount = 500 }, new Person { Name = "Name3", Amount = 300 }, new Person { Name = "Name4", Amount = 300 } }; var subgroup = values.TakeWhileAdding( person => person.Amount, total => total < requestedAmount); foreach (var v in subgroup) Trace.WriteLine(v);` `

` `var count = 0; var exceeds = false; var subgroup = people.OrderBy(x => x.Amount).TakeWhile(x => { if (exceeds) { return false; } count += x.Amount; if (count >= requestedAmount) { x.Amount = requestedAmount - (count - x.Amount); exceeds = true; return true; } return !exceeds; }).ToList();` `