如何同时迭代多个 IEnumerable

发布于 2024-10-15 14:53:05 字数 824 浏览 5 评论 0原文

假设我有两个(或更多)带有许多元素的 IEnumerable 。每个 IEnumerable 都有另一种类型 T。这些列表可能非常长,不应完全加载到内存中。

IEnumerable<int> ints = getManyInts();
IEnumerable<string> strings = getSomeStrings();
IEnumerable<DateTime> dates = getSomeDates();

我想要做的是迭代这些列表,并为每一步获取一个包含一个 int、一个字符串和一个 DateTime 的项目,直到到达最长或最短列表的末尾。这两种情况都应该支持(布尔参数最长与最短左右)。对于较短列表中不可用的每个项目(因为已经到达末尾),我希望使用默认值。

for(Tuple<int,string,DateTime> item in 
    Foo.Combine<int,string,DateTime>(ints, strings, dates))
{
    int i=item.Item1;
    string s=item.Item2;
    DateTime d=item.Item3;
}

是否可以通过使用延迟执行的 linq 来做到这一点? 我知道直接使用 IEnumerators 与收益回报相结合的解决方案。 请参阅如何在 .NET 2 中同时迭代两个 IEnumerable

Assume I have two (or more) IEnumerable<T> with many elements. Every IEnumerable has another type T. The lists can be extreme long and should not be loaded to memory completetly.

IEnumerable<int> ints = getManyInts();
IEnumerable<string> strings = getSomeStrings();
IEnumerable<DateTime> dates = getSomeDates();

What I want to do is to iterate over these lists, and get an item containing one int, one string and one DateTime for each step, until the end of the longest or the shortest list has been reached. Both cases should be supported (bool param longest vs. shortest or so). For every item unavailable in the shorter lists (because the end has already been reached) I'd expect default values.

for(Tuple<int,string,DateTime> item in 
    Foo.Combine<int,string,DateTime>(ints, strings, dates))
{
    int i=item.Item1;
    string s=item.Item2;
    DateTime d=item.Item3;
}

Is it possible to do this with linq using deferred execution?
I know the solution using IEnumerators directly combined with yield return.
See How can I iterate over two IEnumerables simultaneously in .NET 2

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

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

发布评论

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

评论(1

Hello爱情风 2024-10-22 14:53:05

像这样的事情应该可以做到(警告-未经测试):

public static IEnumerable<Tuple<T, U, V>> IterateAll<T, U, V>(IEnumerable<T> seq1, IEnumerable<U> seq2, IEnumerable<V> seq3)
{
    bool ContinueFlag = true;
    using (var e1 = seq1.GetEnumerator())
    using (var e2 = seq2.GetEnumerator())
    using (var e3 = seq3.GetEnumerator())
    {
        do
        {
            bool c1 = e1.MoveNext();
            bool c2 = e2.MoveNext();
            bool c3 = e3.MoveNext();
            ContinueFlag = c1 || c2 || c3;

            if (ContinueFlag)
                yield return new Tuple<T, U, V>(c1 ? e1.Current : default(T), c2 ? e2.Current : default(U), c3 ? e3.Current : default(V));
        } while (ContinueFlag);
    }
}

Something like this should do it (warning- untested):

public static IEnumerable<Tuple<T, U, V>> IterateAll<T, U, V>(IEnumerable<T> seq1, IEnumerable<U> seq2, IEnumerable<V> seq3)
{
    bool ContinueFlag = true;
    using (var e1 = seq1.GetEnumerator())
    using (var e2 = seq2.GetEnumerator())
    using (var e3 = seq3.GetEnumerator())
    {
        do
        {
            bool c1 = e1.MoveNext();
            bool c2 = e2.MoveNext();
            bool c3 = e3.MoveNext();
            ContinueFlag = c1 || c2 || c3;

            if (ContinueFlag)
                yield return new Tuple<T, U, V>(c1 ? e1.Current : default(T), c2 ? e2.Current : default(U), c3 ? e3.Current : default(V));
        } while (ContinueFlag);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文