在Linq中,我们可以使用Enumerable.Zip方法组合两个列表:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector
)
我希望相当于Zip任意数量的相同类型的枚举。方法签名的东西有点像这样:
public static IEnumerable<TResult> Zip<TIn, TResult>(IEnumerable<IEnumerable<TIn>>inputs, Func<IEnumerable<TIn>, TResult> combiner)
当枚举为枚举时,它返回一个包含每个相应可枚举元素的枚举。
这是否存在于任何地方?或者使用现有的Linq方法构建是否简单?聚合多个拉链?
答案 0 :(得分:3)
由于输入是一个数组,您可以创建一个IEnumerator<TIn>[]
然后在每个上面调用MoveNext。像这样:
IEnumerator<T>[] enumerators = inputs.Select(inp => inp.GetEnumerator()).ToArray();
int len = enumerators.Length;
while (true) {
TResult[] result = new TResult[len];
for(int i = 0; i < len; ++i) {
if (!enumerators[i].MoveNext()) yield break;
result[i] = resultSelector(enumerators[i].Current);
}
yield return result;
}
答案 1 :(得分:1)
怎么样,
using System;
using System.Collections.Generic;
using System.Linq;
...
public static IEnumerable<TResult> Zip<T, TResult>(
this IEnumerable<T> source,
Func<IList<T>, TResult> resultSelector,
params IEnumerable<T>[] others)
{
if (resultSelector == null)
{
throw new ArgumentNullException("resultSelector");
}
var enumerators = new List<IEnumerator<T>>(others.Length + 1);
enumerators.Add(source.GetEnumerator());
enumerators.AddRange(others.Select(e => e.GetEnumerator()));
try
{
var buffer = new T[enumerators.Count];
while (true)
{
for (var i = 0; i < enumerators.Count; i++)
{
if (!enumerators[i].MoveNext())
{
yield break;
}
buffer[i] = enumerators[i].Current;
}
yield return resultSelector(buffer);
}
}
finally
{
foreach (var enumerator in enumerators)
{
enumerator.Dispose();
}
}
}