Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging multiple lists

Tags:

c#

.net

list

linq

Given that there I have a list of lists, List<List<T>>, in which all lists contain 0 or more items, likely, but not necessarily all the same number. And I would like tho have a list containing all the items in the Lists... but I want the order to be as follows: first the first items off all the lists, in order that they appear in the 'super-list'.

Ex.

List[0] = { 'Apple', 'Blueberry', 'Cranberry' }
List[1] = { 'Anteater', 'Baboon', 'Camel', 'Dodo'}
List[2] = { 'Albatross', 'Blackbird', 'Chicken'}

result = { 'Apple', 'Anteater', 'Albatross', 'Blueberry', 'Baboon', 
           'Blackbird', 'Cranberry', 'Camel', 'Chicken', 'Dodo' }

(note that this is NOT alphabetical order, Blueberry comes before Baboon)

Ofcourse, i could just loop through the 'superlist' with a counter, adding items to the resultslist one by one, as long as there is a list that isn't empty:

int i = 0;
bool done = false;

while (!done)
{
    bool found = false;

    foreach (list l in superlist)
    {
        if (l.Count() > i)
        {
           found = true;
           result.Add(l[i]);
        }
    }

    i++;

    if (!found)
        done = true;
}

But it would be way nicer to use some optimized LINQ function to do this. I have been looking into Zip, GroupBy and Aggregate, but couldn't get them to work.

So: Is there a pretty LINQ function, or combination of multiple, that would turn this into pretty code, or should I stick by (and maybe optimize) my current function?

Edit: A simple SelectMany(x => x) also doesn't do the trick, as it preserves the order of the lists, instead of folding them, like my algorithm does. See my initial question for more details.

like image 521
Amy Avatar asked Sep 11 '26 21:09

Amy


2 Answers

You need SelectMany

var result = lists.SelectMany(x => x.Select((s, inx) => new { s, inx }))
                .GroupBy(x => x.inx)
                .SelectMany(x => x.Select(y => y.s))
                .ToList();

EDIT

For those, who want to try, the initialization code.

List<List<string>> lists = new List<List<string>>()
        {
            new List<string>(){ "Apple", "Blueberry", "Cranberry" },
            new List<string>(){ "Anteater", "Baboon", "Camel", "Dodo"},
            new List<string>(){ "Albatross", "Blackbird", "Chicken"},
        };

EDIT 2

OUTPUT: Apple,Anteater,Albatross,Blueberry,Baboon,Blackbird,Cranberry,Camel,Chicken,Dodo

like image 72
I4V Avatar answered Sep 13 '26 11:09

I4V


Just use MyListOfLists.SelectMany(x => x).OrderByDescending(x => x).ToList()

SelectMany will flatten your lists into one. OrderByDescending operates on that result and will put the results in alphabetical order (which I think you want). Then call ToList to force execution and get a List<string> instead of an IEnumerable<string>

like image 31
evanmcdonnal Avatar answered Sep 13 '26 09:09

evanmcdonnal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!