LINQ聚合对列表最后一个元素的特殊关注
本文关键字:元素 最后一个 列表 LINQ | 更新日期: 2023-09-27 18:04:51
我想为集合中的最后一个元素传递一个不同的函数给Aggregate
。
它的用法是:
List<string> listString = new List{"1", "2", "3"};
string joined = listString.Aggregate(new StringBuilder(),
(sb,s) => sb.Append(s).Append(", "),
(sb,s) => sb.Append(s)).ToString();
//joined => "1, 2, 3"
如果没有其他自定义实现,将是什么?
注:我想这样做w/可组合函数迭代一次通过集合。换句话说,我不想用String.Join
Select
Aggregate不允许这样做。
您可以携带前一个元素,并在Aggregate
之后进行最终处理。此外,我认为你最好的选择是编写自定义方法,对最后一个(也可能是第一个)元素进行自定义处理。
最后一项的Aggregate
的一些近似代码(不是处理大多数特殊情况,如空/短列表):
var firstLast = seq.Aggregate(
Tuple.Create(new StringBuilder(), default(string)),
(sum, cur) =>
{
if (sum.Item2 != null)
{
sum.Item1.Append(",");
sum.Item1.Append(sum.Item2);
}
return Tuple.Create(sum.Item1, cur);
});
firstLast.Item1.Append(SpecialProcessingForLast(sum.Item2));
return firstLast.Item1.ToString();
Aggregate
与"last"的特殊情况。示例已准备好复制/粘贴到LinqPad/console应用程序,在制作扩展功能时取消注释"this"。Main显示聚合数组,对除最后一个元素外的所有元素求和,最后一个元素从result中减去:
void Main()
{
Console.WriteLine(AggregateWithLast(new[] {1,1,1,-3}, 0, (s,c)=>s+c, (s,c)=>s-c));
Console.WriteLine(AggregateWithLast(new[] {1,1,1,+3}, 0, (s,c)=>s+c, (s,c)=>s-c));
}
public static TAccumulate AggregateWithLast<TSource, TAccumulate>(
/*this */ IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> funcAll,
Func<TAccumulate, TSource, TAccumulate> funcLast)
{
using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
{
if (!sourceIterator.MoveNext())
{
return seed;
}
TSource last = sourceIterator.Current;
TAccumulate total = seed;
while (sourceIterator.MoveNext())
{
total = funcAll(total, last);
last = sourceIterator.Current;
}
return funcLast(total, last);
}
}
注意:如果你只需要String.Join
而不是。net 4.0+中的一个需要IEnumerable<T>
-所以它只会迭代序列一次而不需要ToList
/ToArray
。
对于您的特定示例,另一种方法是跳过第一个元素的逗号,并将其添加到尾部元素,如下所示:
List<string> listString = new() { "1", "2", "3" };
string joined = listString
.Select((value, index) => (value, index))
.Aggregate(new StringBuilder(), (sb, s) =>
s.index == 0
? sb.Append(s.value)
: sb.Append(", ").Append(s.value))
.ToString();
我知道这并不能解决标题中的问题,但对于大多数人来说,"用一些中缀"来连接事物"。问题,这个很好用。也就是说,string.Join
不是解决方案。