views:

307

answers:

3

Is there a simple built-in way to take an ordered list of IEnumerables and return a single IEnumerable which yields, in order, all the elements in the first, then the second, and so on.

I could certainly write my own, but I wanted to know whether there was already a way to accomplish this seemingly useful task before I do it.

+15  A: 

Try SelectMany.

IEnumerable<int> Collapse(IEnumerable<IEnumerable<int>> e){
 return e.SelectMany(x => x );
}

The purpose of this function is to flatten a group of IEnumerable<IEnumerable<T>> into an IEnumerable<T>. The returned data will preserve the original order.

JaredPar
+10  A: 

Further to JaredPar's (correct) answer - also query syntax:

var all = from inner in outer
          from item in inner
          select item;
Marc Gravell
+7  A: 

Further to the (correct) LINQ-based answers...

If you don't want to use LINQ, you can invent a ChainedEnumerable class, using yield:

public class ChainedEnumerable<T> : IEnumerable<T>
{
    private readonly IEnumerable<T>[] _inners;

    public ChainedEnumerable(params IEnumerable<T>[] inners)
    {
        _inners = inners;
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (IEnumerable<T> inner in _inners)
        {
            foreach (T t in inner)
            {
                yield return t;
            }
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Use it like this:

List<string> a = new List<string> { "A1", "A2", "A3" };
List<string> b = new List<string> { "B1", "B2", "B3" };
ChainedEnumerable<string> chainedEnumerable =
    new ChainedEnumerable<string>(a, b);
foreach (string s in chainedEnumerable)
    Console.WriteLine(s);
Roger Lipscombe