2008-09-19 11 views
12

En Python hay una función muy ordenado llamada zip que se puede utilizar para iterar a través de dos listas al mismo tiempo:¿Hay un método zip en .Net?

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

El código anterior debe producir lo siguiente:

1 a 
2 b 
3 c

Me pregunto si hay un método como este disponible en .Net? Estoy pensando en escribirlo yo mismo, pero no tiene sentido si ya está disponible.

+0

Podría alguien explicar cómo esto es diferente de sólo un bucle "for" como: for (var i; ;) {var x = arr1 [i]; var y = arr2 [i]; } Asumo que hay una diferencia compleja que no estoy viendo aquí. –

+2

Allen, no existe, al menos no para matrices. Sin embargo, zip funcionará con cualquier cosa que pueda iterar, no solo por ej. matrices. –

+0

Allen: zip() es una expresión. Tu alternativa es un bloque de código. – recursive

Respuesta

25

Actualización: Es una función de en C# 4 como System.Linq.Enumerable.Zip Method

Aquí está una versión de 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); 
    } 
} 

dejó caer el Versión C# 2 ya que estaba mostrando su edad.

+0

Sería bueno definir el par <,> también o tomar un parámetro adicional que sirva como selector de resultados. –

+0

Guau, estoy sorprendido. Mientras escribía mi respuesta, proporciona casi el 100% de la solución similar :) – aku

+0

Esta es una de las situaciones ideales para usar la palabra clave "var" (si estaba en 3.5): foreach (var pair in Zip (ints, strings))) Usted pierde el ruido de la declaración Pair que para mí no es necesaria. –

5

No, no existe tal función en .NET. Has implementado el tuyo. Tenga en cuenta que C# no es compatible con las tuplas, por lo que el azúcar de sintaxis similar a Pitón también falta.

se puede usar algo como esto:

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); 
} 
+0

+1 para usar usando bloques –

8

Por lo que yo sé, no lo es. Me escribió una para mí (así como algunas otras extensiones útiles y ponerlos en un proyecto llamado NExtension en CodePlex.

Al parecer, las extensiones paralelas para .NET tienen una función Zip.

Aquí es una versión simplificada de NExtension (pero por favor, echa un vistazo a los métodos de extensión más útiles):

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

Uso:

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); 
+0

Buena respuesta. Debería agregar un ejemplo de cómo usar la función en C# 3.0 – Coincoin

+0

mismo comentario aquí que la respuesta aceptada, IEnumerator es IDisposable, debe agregar algunos bloques de uso. –

2

Hay también uno en Fa #:

Let cremallera = Seq.zip firstEnumeration secondEnumation

Cuestiones relacionadas