【问题标题】:How can I iterate over several IEnumerables simultaneously如何同时迭代多个 IEnumerable
【发布时间】:2011-06-20 18:57:12
【问题描述】:

假设我有两个(或更多)IEnumerable<T>,其中包含许多元素。每个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 直接结合收益回报的解决方案。 见How can I iterate over two IEnumerables simultaneously in .NET 2

【问题讨论】:

  • 您正在寻找一个接受两个以上参数的Zip 函数。
  • 使用 var result = s1.Zip(s2.Zip(s3, (a,b) =&gt; new {a,b}), (a,b) =&gt; new {a=a, b=b.a, c=b.b}); 之类的东西可以轻松做到这一点
  • 如果 s2 是最长的列表而 s1 只有很少的元素怎么办?

标签: .net linq performance foreach deferred-execution


【解决方案1】:

应该这样做(警告-未经测试):

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

【讨论】:

  • 是的,这就是我在问题末尾的意思。我希望有一种高性能的 linq 方法。
  • @matthias - 这仍然是 linq 兼容的,并且仍然像其他 linq 运算符一样执行。
  • 我知道,这与 Linq 兼容。它只是“返回”另一个 IEnumerable。
猜你喜欢
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-07
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 2023-01-12
相关资源
最近更新 更多