在C#中压缩多个/任意数量的enumerables[英] Zip multiple/abitrary number of enumerables in C#

本文是小编为大家收集整理的关于在C#中压缩多个/任意数量的enumerables的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

在 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 方法构建是否简单?聚合多个 zip?

推荐答案

由于输入是一个数组,所以可以创建一个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;
}

本文地址:https://www.itbaoku.cn/post/1556918.html

问题描述

In Linq we can combine two lists with a the Enumerable.Zip method:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
    this IEnumerable<TFirst> first,
    IEnumerable<TSecond> second,
    Func<TFirst, TSecond, TResult> resultSelector
)

I would like the equivalent to Zip an arbitrary number of enumerables of the same type. Something with a method signature a bit like this:

public static IEnumerable<TResult> Zip<TIn, TResult>(IEnumerable<IEnumerable<TIn>>inputs, Func<IEnumerable<TIn>, TResult> combiner)

Where the as the enumerable is iterated, it returns an enumerable containing an element from each of the corresponding enumerables.

Does this exist anywhere? Or is it simple to build with existing Linq methods? Aggregate multiple zips?

推荐答案

Since the input is an array, you can create an IEnumerator<TIn>[] Then call MoveNext on each of them. Something like this:

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;
}