How to combine IEnumerable<string[]>

I'm trying to work on improving my LINQ skills, while at the same time beginning with Code Kata. Right now, I'm trying to improve my work on this Kata by using LINQ instead of foreach loops.

The requirements:

Have a method that will split a string on new lines ('\n') into separate strings, and then split each of those on commas to a max of two numbers each.

Here's what I have so far:

private int Add(string numbers) {
    var arrays = numbers.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
    var list = arrays.Select(s => s.Split(new char[] { ',', }, StringSplitOptions.RemoveEmptyEntries));

    // Additional code here...
}

As it stands right now, list is an IEnumerable<string[]>. I have been looking through the various LINQ methods (Join(), Aggregate(), etc), but haven't found anything that returns IEnumerable<string>. I'm starting to think that I'll need to write an extension method for that, but was hoping to see if there was an alternative I was missing.

EDIT

My end goal with this is to wind up with an IEnumerable<int>, though I was thinking I'd have to make a stop at an IEnumerable<string> before that point. If that can be combined into one step, that'd be even better.

Jon Skeet
people
quotationmark

Fortunately it's really simple - you just want SelectMany, which acts as a "flatten" operation:

IEnumerable<string> strings = list.SelectMany(x => x);

Or avoid Select to start with, and go straight to SelectMany:

IEnumerable<string> list = arrays.SelectMany(s => s.Split(new char[] { ',', }, 
                                         StringSplitOptions.RemoveEmptyEntries));

(Obviously you can use var for both of these - I've only included the type for clarity.)

And as Habib has mentioned, you don't even need the intermediate arrays variable:

IEnumerable<string> list =
     numbers.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
            .SelectMany(s => s.Split(new char[] { ',' }, 
                                     StringSplitOptions.RemoveEmptyEntries));

And to get an IEnumerable<int>:

IEnumerable<int> list =
     numbers.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
            .SelectMany(s => s.Split(new char[] { ',' }, 
                                     StringSplitOptions.RemoveEmptyEntries))
            .Select(s => int.Parse(s));

This will throw an exception (lazily) if any of the strings can't be parsed as an integer.

people

See more on this question at Stackoverflow