views:

67

answers:

2

I have a variable that contains :
Sometimes array of strings and sometimes array of array of strings
e.g:

var words = a LINQ to XML query;
//words == { "01", "02", "03", ... }
//or
//words == { {"01", "02", "03"}, {"04", "05", "06"}, ... }

Now , I wanna access to each item in the words array with a for statement
Could you please guide me ?
Thanks

+2  A: 

You can convert the second form to the first using SelectMany:

string[] words = words2.SelectMany(x => x).ToArray();
Mark Byers
... with a call to `ToArray()` at the end, of course, if you want to get that to compile. Or just use `IEnumerable<string>` or `var` otherwise.
Jon Skeet
Thanks Jon, done!
Mark Byers
+3  A: 

(Note: please see the edit...)

If you don't actually know beforehand whether you've got a string array or an array of arrays of strings, you'll need to conditionally call SelectMany:

string[][] multi = words as string[][];
string[] flattened = multi == null ? words : multi.SelectMany(x => x).ToArray();

Note that in this case if you change the contents of flattened, that will either change words (if that was already flat) or just change a copy (if it was a jagged array). If you want to make it consistent, you could call words.ToArray() in second operand of the conditional operator:

string[] flattened = 
    multi == null ? words.ToArray() : multi.SelectMany(x => x).ToArray();

Is there no way you can avoid the ambiguity to start with though? In particular, if you're in control over the LINQ to XML queries involved, you should be able to make them give a consistent result type.

EDIT: I've just realised that if you don't know the type of the data to start with, then words is presumably declared as just object or perhaps IEnumerable. In that case, you'd want something like this:

public string[] Flatten(object words)
{
    string[][] multi = words as string[][];
    if (multi != null)
    {
        return multi.SelectMany(x => x).ToArray();
    }
    string[] single = words as string[];
    if (single != null)
    {
        return single.ToArray(); // Defensive copy; remove if not needed
    }
    throw new ArgumentException("Argument must be string[] or string[][]");
}

This is still really icky - you should definitely try to make the queries give you some consistent result type instead.

Jon Skeet
@Jon - I'm not sure the ambiguity is a problem. I tried `SelectMany` on just a `string[]` and a `string[][]` and it worked in both cases.
Mike Two
SelectMany on a string[] will give you an `IEnumerable<char>` which isn't what you want.
Jon Skeet
@Jon - You're right. I only used single character strings in my test so it looked great. That was a bad idea.
Mike Two