如何在 C# 中进行 Python 的 zip 操作?

发布于 2024-08-24 09:15:50 字数 175 浏览 6 评论 0 原文

Python 的 zip 函数执行以下操作

a = [1, 2, 3]
b = [6, 7, 8]
zipped = zip(a, b)

[[1, 6], [2, 7], [3, 8]]

Python's zip function does the following:

a = [1, 2, 3]
b = [6, 7, 8]
zipped = zip(a, b)

result

[[1, 6], [2, 7], [3, 8]]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

风吹过旳痕迹 2024-08-31 09:15:50

怎么样 这个

C# 4.0 LINQ 的新 Zip 运算符

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

How about this?

C# 4.0 LINQ'S NEW ZIP OPERATOR

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
        this IEnumerable<TFirst> first,
        IEnumerable<TSecond> second,
        Func<TFirst, TSecond, TResult> func);
晨曦慕雪 2024-08-31 09:15:50

解决方案2:与C# 4.0 Zip类似,但可以在C# 3.0中使用它

    public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
        this IEnumerable<TFirst> first,
        IEnumerable<TSecond> second,
        Func<TFirst, TSecond, TResult> func)
    {
        using(var enumeratorA = first.GetEnumerator())
        using(var enumeratorB = second.GetEnumerator())
        {
            while (enumeratorA.MoveNext())
            {
                enumeratorB.MoveNext();
                yield return func(enumeratorA.Current, enumeratorB.Current);
            }
        }
    }

Solution 2: Similar to C# 4.0 Zip, but you can use it in C# 3.0

    public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
        this IEnumerable<TFirst> first,
        IEnumerable<TSecond> second,
        Func<TFirst, TSecond, TResult> func)
    {
        using(var enumeratorA = first.GetEnumerator())
        using(var enumeratorB = second.GetEnumerator())
        {
            while (enumeratorA.MoveNext())
            {
                enumeratorB.MoveNext();
                yield return func(enumeratorA.Current, enumeratorB.Current);
            }
        }
    }
七堇年 2024-08-31 09:15:50

这是 Python zip 的更现代的版本:

public static IEnumerable<(T1, T2)> Zip<T1, T2>(this IEnumerable<T1> t1, IEnumerable<T2> t2)
{
    using var t1e = t1.GetEnumerator();
    using var t2e = t2.GetEnumerator();
    while (t1e.MoveNext() && t2e.MoveNext())
        yield return (t1e.Current, t2e.Current);
}

public static IEnumerable<(T1, T2, T3)> Zip<T1, T2, T3>(this IEnumerable<T1> t1, IEnumerable<T2> t2, IEnumerable<T3> t3)
{
    using var t1e = t1.GetEnumerator();
    using var t2e = t2.GetEnumerator();
    using var t3e = t3.GetEnumerator();
    while (t1e.MoveNext() && t2e.MoveNext() && t3e.MoveNext())
        yield return (t1e.Current, t2e.Current, t3e.Current);
}

很容易制作更多扩展来同时处理更多 IEnumerable ,为了简洁起见,我将其保留为 2 和 3 版本。

Here's a more modern rendition of Python's zip:

public static IEnumerable<(T1, T2)> Zip<T1, T2>(this IEnumerable<T1> t1, IEnumerable<T2> t2)
{
    using var t1e = t1.GetEnumerator();
    using var t2e = t2.GetEnumerator();
    while (t1e.MoveNext() && t2e.MoveNext())
        yield return (t1e.Current, t2e.Current);
}

public static IEnumerable<(T1, T2, T3)> Zip<T1, T2, T3>(this IEnumerable<T1> t1, IEnumerable<T2> t2, IEnumerable<T3> t3)
{
    using var t1e = t1.GetEnumerator();
    using var t2e = t2.GetEnumerator();
    using var t3e = t3.GetEnumerator();
    while (t1e.MoveNext() && t2e.MoveNext() && t3e.MoveNext())
        yield return (t1e.Current, t2e.Current, t3e.Current);
}

It's easy to make more extensions that handle more IEnumerables at once, I've kept it to the 2 and 3 versions for brevity.

不再让梦枯萎 2024-08-31 09:15:50

解决方案一:

IEnumerable<KeyValuePair<T1, T2>> Zip<T1, T2>(
    IEnumerable<T1> a, IEnumerable<T2> b)
{
    var enumeratorA = a.GetEnumerator();
    var enumeratorB = b.GetEnumerator();
    while (enumeratorA.MoveNext())
    {
        enumeratorB.MoveNext();
        yield return new KeyValuePair<T1, T2>
        (
            enumeratorA.Current,
            enumeratorB.Current
        );
    }
}

Solution 1:

IEnumerable<KeyValuePair<T1, T2>> Zip<T1, T2>(
    IEnumerable<T1> a, IEnumerable<T2> b)
{
    var enumeratorA = a.GetEnumerator();
    var enumeratorB = b.GetEnumerator();
    while (enumeratorA.MoveNext())
    {
        enumeratorB.MoveNext();
        yield return new KeyValuePair<T1, T2>
        (
            enumeratorA.Current,
            enumeratorB.Current
        );
    }
}
贱人配狗天长地久 2024-08-31 09:15:50

另请查看 Cadenza,它具有各种漂亮的实用方法。

具体查看 Cadenza.Collections.EnumerableCoda< /a>.

Also take a look at Cadenza which has all sorts of nifty utility methods.

Specifically look at the Zip extension methods under Cadenza.Collections.EnumerableCoda.

鹿童谣 2024-08-31 09:15:50

我刚刚遇到了同样的问题。 .NET库没有提供解决方案,所以我自己做了。这是我的解决方案。

Pivot 方法作为 IEnumerable> 的扩展。
它要求所有序列的元素具有相同的类型T

public static class LinqUtil
{
    /// <summary>
    /// From a number of input sequences makes a result sequence of sequences of elements
    /// taken from the same position of each input sequence.
    /// Example: ((1,2,3,4,5), (6,7,8,9,10), (11,12,13,14,15)) --> ((1,6,11), (2,7,12), (3,8,13), (4,9,14), (5,10,15))
    /// </summary>
    /// <typeparam name="T">Type of sequence elements</typeparam>
    /// <param name="source">source seq of seqs</param>
    /// <param name="fillDefault">
    /// Defines how to handle situation when input sequences are of different length.
    ///     false -- throw InvalidOperationException
    ///     true  -- fill missing values by the default values for the type T.
    /// </param>
    /// <returns>Pivoted sequence</returns>
    public static IEnumerable<IEnumerable<T>> Pivot<T>(this IEnumerable<IEnumerable<T>> source, bool fillDefault = false)
    {
        IList<IEnumerator<T>> heads = new List<IEnumerator<T>>();

        foreach (IEnumerable<T> sourceSeq in source)
        {
            heads.Add(sourceSeq.GetEnumerator());
        }

        while (MoveAllHeads(heads, fillDefault))
        {
            yield return ReadHeads(heads);
        }
    }

    private static IEnumerable<T> ReadHeads<T>(IEnumerable<IEnumerator<T>> heads)
    {
        foreach (IEnumerator<T> head in heads)
        {
            if (head == null)
                yield return default(T);
            else
                yield return head.Current;
        }
    }

    private static bool MoveAllHeads<T>(IList<IEnumerator<T>> heads, bool fillDefault)
    {
        bool any = false;
        bool all = true;

        for (int i = 0; i < heads.Count; ++i)
        {
            bool hasNext = false;

            if(heads[i] != null) hasNext = heads[i].MoveNext();

            if (!hasNext) heads[i] = null;

            any |= hasNext;
            all &= hasNext;
        }

        if (any && !all && !fillDefault)
            throw new InvalidOperationException("Input sequences are of different length");

        return any;
    }
}

I just have come across the same problem. .NET library does not offer the solution, so I made it by myself. Here is my solution.

The Pivot method is made as extension to IEnumerable<IEnumerable<T>>.
It requires all the sequences' elements to be of the same type T.

public static class LinqUtil
{
    /// <summary>
    /// From a number of input sequences makes a result sequence of sequences of elements
    /// taken from the same position of each input sequence.
    /// Example: ((1,2,3,4,5), (6,7,8,9,10), (11,12,13,14,15)) --> ((1,6,11), (2,7,12), (3,8,13), (4,9,14), (5,10,15))
    /// </summary>
    /// <typeparam name="T">Type of sequence elements</typeparam>
    /// <param name="source">source seq of seqs</param>
    /// <param name="fillDefault">
    /// Defines how to handle situation when input sequences are of different length.
    ///     false -- throw InvalidOperationException
    ///     true  -- fill missing values by the default values for the type T.
    /// </param>
    /// <returns>Pivoted sequence</returns>
    public static IEnumerable<IEnumerable<T>> Pivot<T>(this IEnumerable<IEnumerable<T>> source, bool fillDefault = false)
    {
        IList<IEnumerator<T>> heads = new List<IEnumerator<T>>();

        foreach (IEnumerable<T> sourceSeq in source)
        {
            heads.Add(sourceSeq.GetEnumerator());
        }

        while (MoveAllHeads(heads, fillDefault))
        {
            yield return ReadHeads(heads);
        }
    }

    private static IEnumerable<T> ReadHeads<T>(IEnumerable<IEnumerator<T>> heads)
    {
        foreach (IEnumerator<T> head in heads)
        {
            if (head == null)
                yield return default(T);
            else
                yield return head.Current;
        }
    }

    private static bool MoveAllHeads<T>(IList<IEnumerator<T>> heads, bool fillDefault)
    {
        bool any = false;
        bool all = true;

        for (int i = 0; i < heads.Count; ++i)
        {
            bool hasNext = false;

            if(heads[i] != null) hasNext = heads[i].MoveNext();

            if (!hasNext) heads[i] = null;

            any |= hasNext;
            all &= hasNext;
        }

        if (any && !all && !fillDefault)
            throw new InvalidOperationException("Input sequences are of different length");

        return any;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文