2010-05-11 9 views
5

In altre lingue (Ruby, Python, ...) posso usare zip(list1, list2) che funziona in questo modo:Linq/.NET3.5 supporta un metodo 'zip'?

Se list1 is {1,2,3,4} e list2 is {a,b,c}

poi zip(list1, list2) restituisce: {(1,a), (2,b), (3,c), (d,null)}

È un tale metodo a disposizione nelle estensioni Linq di .NET?

risposta

12

.NET 4 ci fornisce un metodo Zip ma non è disponibile in .NET 3.5. Se sei curioso, Eric Lippert provides an implementation of Zip che potresti trovare utile.

+0

risposto con un'implementazione di sotto che fa – katbyte

+0

@Steven: No, non è così: http://referencesource.microsoft.com/#System.Core/ Sistema/Linq/Enumerable.cs, 2b8d0f02389aab71 – Heinzi

0

Nessuna implementazione inserirà i valori mancanti (o controllerà che le lunghezze siano uguali) della domanda posta.

qui è un'implementazione che può:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector, bool checkLengths = true, bool fillMissing = false) { 
     if (first == null) { throw new ArgumentNullException("first");} 
     if (second == null) { throw new ArgumentNullException("second");} 
     if (selector == null) { throw new ArgumentNullException("selector");} 

     using (IEnumerator<TFirst> e1 = first.GetEnumerator()) { 
      using (IEnumerator<TSecond> e2 = second.GetEnumerator()) { 
       while (true) { 
        bool more1 = e1.MoveNext(); 
        bool more2 = e2.MoveNext(); 

        if(! more1 || ! more2) { //one finished 
         if(checkLengths && ! fillMissing && (more1 || more2)) { //checking length && not filling in missing values && ones not finished 
          throw new Exception("Enumerables have different lengths (" + (more1 ? "first" : "second") +" is longer)"); 
         } 

         //fill in missing values with default(Tx) if asked too 
         if (fillMissing) { 
          if (more1) { 
           while (e1.MoveNext()) { 
            yield return selector(e1.Current, default(TSecond));   
           } 
          } else { 
           while (e2.MoveNext()) { 
            yield return selector(default(TFirst), e2.Current);   
           } 
          } 
         } 

         yield break; 
        } 

        yield return selector(e1.Current, e2.Current); 
       } 
      } 
     } 
    } 
+0

+1 per notare il comportamento dei "valori mancanti". Tuttavia, questo è un errore da parte mia - assomiglia alla [funzione 'zip' di Python] (http://docs.python.org/2/library/functions.html#zip) * si ferma * anche quando si raggiunge la fine di il suo argomento * più breve *, proprio come la versione di Linq. (E la mia ipotesi - mostrata nella domanda - era errata) –

+0

È strano per una funzione zip, quindi non è impostata per default. Ma ho avuto alcune situazioni in cui era auspicabile. – katbyte

Problemi correlati