user6060080
user6060080

Reputation:

Convert List<dynamic> to List using LINQ

I'm having a collection List<dynamic> dList. In that, it has string items and List<string> items. Now I need to organize all the values in a single List.

Just refer the List<dynamic> dList

Case: 1

List<dynamic> dList = new List<dynamic>()
{
    "Selva",
    new List<string>() {"Bala"},
    new List<string>() {"Prayag", "Raj"},
    "Pavithran"
};

Case: 2

List<object> bala = new List<dynamic>()
{
    "Selva",
    new List<object>() {"Bala"},
    new List<object>() {"Prayag", "Raj"},
    "Pavithran"
};

The Output of the above two List are

enter image description here

My Expected Output is

enter image description here

How could I achieve the expected result from the above List<dynamic>? The List is generated at run time and I cannot to change the structure.

This is a small part of a complex Linq query, so, I need to achieve this in Linq.

Upvotes: 1

Views: 6394

Answers (2)

RB.
RB.

Reputation: 37172

If order is important then you can convert every element to a List<string> and then flatten these:

List<dynamic> dList = new List<dynamic>()
{
    "Selva",
    new List<string>() {"Bala"},
    new List<string>() {"Prayag", "Raj"},
    "Pavithran"
};

var flattenedList = dList.SelectMany(d => 
{
    if (d is string) 
    {
        return new List<string>() { d };
    }
    else if (d is List<string>)
    {
        return (d as List<string>);
    }
    else 
    {
        throw new Exception("Type not recognised");
    }
});

Or, as a sexy one-liner with no type-checking (so...use at your own risk!)

dList.SelectMany(d => d as List<string> ?? new List<string>() { d })

Or, finally, in LINQ syntax:

var newList = 
    (from d in dList
    from d2 in EnsureListOfString((object)d)
    select d2
    );

public List<string> EnsureListOfString(object arg) 
{
    List<string> rtn = arg as List<string>;

    if (rtn == null) 
    {
        if (arg is string)
        {
            rtn = new List<string>() { arg as string };
        }
        else 
        {
            throw new Exception("Type not recognised.");
        }
    }

    return rtn;
}

Upvotes: 5

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43876

If the order of the elements is not important, you can do this:

dList.OfType<string>().Concat(dList.OfType<List<string>>().SelectMany(l => l));

This first selects all string elements from the list, then selects all List<string> elements and flattens them using SelectMany and finally concats all strings.

Upvotes: 1

Related Questions