Question

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

Was it helpful?

Solution

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);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top