Linq/.NET3.5 是否支持“zip”?方法?

发布于 2024-09-01 15:10:41 字数 272 浏览 8 评论 0原文

在其他语言(ruby,python,...)中,我可以使用 zip(list1, list2) ,其工作原理如下:

如果 list1 是 {1,2,3,4} code> 和 list2 是 {a,b,c}

那么 zip(list1, list2) 将返回:{(1,a), (2,b ), (3,c), (d,null)}

.NET 的 Linq 扩展中是否有这样的方法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暗恋未遂 2024-09-08 15:10:41

.NET 4 为我们提供了一个 Zip 方法但它在 .NET 3.5 中不可用。如果您好奇,Eric Lippert 提供了一个实现Zip 您可能会觉得有用。

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

朕就是辣么酷 2024-09-08 15:10:41

两种实现都不会按照所提出的问题填充缺失值(或检查长度是否相同)。

这是一个可以:

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

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);
                }
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文