Как я могу перебрать несколько IEnumerables одновременно - PullRequest
5 голосов
/ 03 февраля 2011

Предположим, у меня есть два (или более) IEnumerable<T> со многими элементами. Каждый IEnumerable имеет другой тип T. Списки могут быть очень длинными и не должны полностью загружаться в память.

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

Что я хочу сделать, так это перебирать эти списки и получать элемент, содержащий один int, одну строку и один DateTime для каждого шага, пока не будет достигнут конец самого длинного или самого короткого списка. Оба случая должны быть поддержаны (параметр bool самый длинный или самый короткий или около того). Для каждого элемента, недоступного в более коротких списках (потому что конец уже достигнут), я ожидаю значения по умолчанию.

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, непосредственно объединенное с доходностью. См. Как я могу перебрать два IEnumerables одновременно в .NET 2

1 Ответ

4 голосов
/ 03 февраля 2011

Что-то вроде этого должно сделать (предупреждение - не проверено):

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