我想为集合中的最后一个元素传递一个不同的函数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"
如果没有其他存在,那么自定义实现是什么?
P.S。我想做这个w /可组合函数迭代一次通过集合。换句话说,我不想在Select
String.Join
答案 0 :(得分:2)
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
以及“最后”的特殊情况。样本已准备好复制/粘贴到LinqPad / console应用程序,在进行扩展功能时取消注释“this”。 Main显示聚合数组,除了最后一个元素之外的所有元素,从结果中减去最后一个:
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
。