Does Linq/.NET3.5 support a 'zip' method?
Asked Answered
D

2

6

In other languages (ruby, python, ...) I can use zip(list1, list2) which works like this:

If list1 is {1,2,3,4} and list2 is {a,b,c}

then zip(list1, list2) would return: {(1,a), (2,b), (3,c), (d,null)}

Is such a method available in .NET's Linq extensions?

Deify answered 11/5, 2010 at 15:4 Comment(0)
C
13

.NET 4 gives us a Zip method but it is not available in .NET 3.5. If you are curious, Eric Lippert provides an implementation of Zip that you may find useful.

Catchup answered 11/5, 2010 at 15:6 Comment(2)
answered with an implementation below that doesPresentiment
@Steven: No, it doesn't: referencesource.microsoft.com/#System.Core/System/Linq/…Fives
P
0

neither implementation will fill in the missing values (or check that the lengths are the same) as the question asked.

here is an implementation that can:

    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);
                }
            }
        }
    }
Presentiment answered 9/1, 2014 at 6:37 Comment(2)
+1 for noticing the 'missing values' behaviour. However, this is an error on my part - it looks like Python's zip function also stops when reaching the end of its shortest argument, just like the Linq version. (And my assumption - shown in the question - was wrong)Deify
It is odd for a zip function, hence it defaults to not. But I have had a few situations were it was desirable.Presentiment

© 2022 - 2024 — McMap. All rights reserved.