【问题标题】:Is there a zip-like method in .Net?.Net 中有类似 zip 的方法吗?
【发布时间】:2010-09-11 04:46:35
【问题描述】:

在 Python 中有一个非常简洁的函数称为 zip,可用于同时遍历两个列表:

list1 = [1, 2, 3]
list2 = ["a", "b", "c"]
for v1, v2 in zip(list1, list2):
    print v1 + " " + v2

以上代码应产生以下内容:

1个
2 乙
3 c

我想知道.Net 中是否有类似的方法?我正在考虑自己写它,但如果它已经可用,那就没有意义了。

【问题讨论】:

  • 有人能解释一下这与“for”循环有何不同,例如: for (var i ; ; ){ var x = arr1[i];变量 y = arr2[i];我假设有一个我在这里没有看到的复杂差异。
  • 艾伦,没有,至少没有数组。但是, zip 将适用于您可以迭代的任何内容,而不仅仅是例如数组。
  • 艾伦:zip() 是一个表达式。您的替代方案是一段代码。

标签: .net python list iteration


【解决方案1】:

更新:它在 C# 4 中内置为 System.Linq.Enumerable.Zip Method

这是一个 C# 3 版本:

IEnumerable<TResult> Zip<TResult,T1,T2>
    (IEnumerable<T1> a,
     IEnumerable<T2> b,
     Func<T1,T2,TResult> combine)
{
    using (var f = a.GetEnumerator())
    using (var s = b.GetEnumerator())
    {
        while (f.MoveNext() && s.MoveNext())
            yield return combine(f.Current, s.Current);
    }
}

由于 C# 2 版本过时而放弃了它。

【讨论】:

  • 最好也定义 Pair 或采用额外的参数作为结果选择器。
  • 哇,我很惊讶。当我输入我的答案时,您提供了几乎 100% 相似的解决方案 :)
  • 这是使用“var”关键字的理想情况之一(如果你在 3.5 上): foreach (var pair in Zip(ints, strings)) 你失去了对的噪音 对我来说不需要的声明。
  • Garry:我同意,但是 C# 2.0 的使用范围仍然更广,所以我想我会在这个例子中坚持使用它。
【解决方案2】:

据我所知没有。我为自己写了一个(以及一些其他有用的扩展,并将它们放在 Codeplex 上一个名为 NExtension 的项目中。

显然 .NET 的 Parallel 扩展具有 Zip 功能。

这是 NExtension 的简化版本(但请查看它以了解更多有用的扩展方法):

public static IEnumerable<TResult> Zip<T1, T2, TResult>(this IEnumerable<T1> source1, IEnumerable<T2> source2, Func<T1, T2, TResult> combine)
{
    using (IEnumerator<T1> data1 = source1.GetEnumerator())
    using (IEnumerator<T2> data2 = source2.GetEnumerator())
        while (data1.MoveNext() && data2.MoveNext())
        {
            yield return combine(data1.Current, data2.Current);
        }
}

用法:

int[] list1 = new int[] {1, 2, 3};
string[] list2 = new string[] {"a", "b", "c"};

foreach (var result in list1.Zip(list2, (i, s) => i.ToString() + " " + s))
    Console.WriteLine(result);

【讨论】:

  • 不错的答案。您应该添加一个如何在 C# 3.0 中使用该函数的示例
  • 这里的评论与接受的答案相同,IEnumerator 是 IDisposable,你应该添加一些 using-blocks。
【解决方案3】:

F#中也有一个:

让 zipped = Seq.zip firstEnumeration secondEnumation

【讨论】:

    【解决方案4】:

    不,.NET 中没有这样的功能。你已经推出了自己的。请注意,C# 不支持元组,因此也缺少类似 python 的语法糖。

    你可以这样使用:

    class Pair<T1, T2>
    {
        public T1 First { get; set;}
        public T2 Second { get; set;}
    }
    
    static IEnumerable<Pair<T1, T2>> Zip<T1, T2>(IEnumerable<T1> first, IEnumerable<T2> second)
    {
        if (first.Count() != second.Count())
            throw new ArgumentException("Blah blah");
    
        using (IEnumerator<T1> e1 = first.GetEnumerator())
        using (IEnumerator<T2> e2 = second.GetEnumerator())
        {
            while (e1.MoveNext() && e2.MoveNext())
            {
                yield return new Pair<T1, T2>() {First = e1.Current, Second = e2.Current};
            }
        }
    }
    
    ...
    
    var ints = new int[] {1, 2, 3};
    var strings = new string[] {"A", "B", "C"};
    
    foreach (var pair in Zip(ints, strings))
    {
        Console.WriteLine(pair.First + ":" + pair.Second);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-30
      • 2012-11-27
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      相关资源
      最近更新 更多