你想要的是 Aggregate 和 TakeWhile 的组合,所以我们来写吧。
public static IEnumerable<S> AggregatingTakeWhile<S, A>(
this IEnumerable<S> items,
A initial,
Func<A, S, A> accumulator,
Func<A, S, bool> predicate)
{
A current = initial;
foreach(S item in items)
{
current = accumulator(current, item);
if (!predicate(current, item))
break;
yield return item;
}
}
所以现在你可以说
var items = myObjList.AggregatingTakeWhile(
0,
(a, s) => a + s.MyValue,
(a, s) => a <= 5);
请注意,我已决定在累加器更新后查询谓词;根据您的应用程序,您可能需要稍微调整一下。
另一种解决方案是将聚合与枚举结合起来:
public static IEnumerable<(A, S)> RunningAggregate<S, A>(
this IEnumerable<S> items,
A initial,
Func<A, S, A> accumulator)
{
A current = initial;
foreach(S item in items)
{
current = accumulator(current, item);
yield return (current, item);
}
}
现在你想要的操作是
var result = myObjList
.RunningAggregate(0, (a, s) => a + s.MyValue)
.TakeWhile( ((a, s)) => a <= 5)
.Select(((a, s)) => s);
我可能在那里弄错了元组语法;我现在没有方便的 Visual Studio。但你明白了。聚合产生一个 (sum, item) 元组的序列,现在我们可以在那个东西上使用普通的序列运算符。