开发者

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

开发者 https://www.devze.com 2022-12-30 09:44 出处:网络
In other languages (ruby, python, ...) I can use zip开发者_如何学C(list1, list2) which works like this:

In other languages (ruby, python, ...) I can use zip开发者_如何学C(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?


.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.


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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号