如何同时迭代几个IEnumerables

时间:2011-02-03 16:13:48

标签: .net linq performance foreach deferred-execution

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

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

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

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执行此操作? 我知道使用IEnumerator直接结合yield return的解决方案。 见How can I iterate over two IEnumerables simultaneously in .NET 2

1 个答案:

答案 0 :(得分:4)

这样的事情应该这样做(警告未经测试):

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