Как объединить список списков с элементами одного типа в один список элементов?

210

Вопрос сбивает с толку, но он намного более понятен, как описано в следующих кодах:

   List<List<T>> listOfList;
   // add three lists of List<T> to listOfList, for example
   /* listOfList = new {
        { 1, 2, 3}, // list 1 of 1, 3, and 3
        { 4, 5, 6}, // list 2
        { 7, 8, 9}  // list 3
        };
   */
   List<T> list = null;
   // how to merger all the items in listOfList to list?
   // { 1, 2, 3, 4, 5, 6, 7, 8, 9 } // one list
   // list = ???

Не уверены, возможно ли это с помощью C # LINQ или Lambda?

По сути, как я могу объединить или " сгладить " список списков?

David.Chu.ca
источник

Ответы:

456

Используйте метод расширения SelectMany

list = listOfList.SelectMany(x => x).ToList();
JaredPar
источник
73
Интересно, сколько людей написали свое собственное расширение "Flatten", не понимая, как работает SelectMany?
Джеймс Шек
1
Почему x => x необходим для этого? Я обычно вижу такие вещи, как х => х +1, но не х => х.
SwimBikeRun
9
@SwimBikeRun SelectMany используется, чтобы взять IEnumerable из TSources, преобразовать каждый TSource в списке в IEnumerable из TResults, а затем объединить все эти IEnumerables в один большой. В этом случае у вас есть список списков для запуска, поэтому, если вы хотите объединить их, функция преобразования из TSource (который является IEnumerable of TResults) в IEnumerable из TResults является функцией тождества (x => x). Это на самом деле просто особый случай, когда вам не нужен дополнительный шаг превращения каждого TSource в список, потому что это уже список.
Шон
@JaredPar мы можем применить эту логику к списку <список <список <T >>>?
Tk1993
4
@TusharKukreti Конечно, просто используйтеlist.SelectMany(x => x.SelectMany(y => y)).ToList();
Брэндон Крамер
13

Вот интегрированная версия синтаксиса C #:

var items =
    from list in listOfList
    from item in list
    select item;
Джо Чунг
источник
Немного смущает, но приятно. Как это? var items = из элемента в списке (из списка в списке выбора списка) выбрать элемент
David.Chu.ca
4
'Double from' - то же самое, что SelectMany ... SelectMany, вероятно, самый мощный из методов LINQ (или операторов запросов). Чтобы понять почему, Google "LINQ SelectMany Monad", и вы узнаете больше, чем вы хотите знать об этом.
Ричард Энтони Хейн
3
Не включайте кавычки при поиске "LINQ SelectMany Monad", иначе он просто вернет вас сюда.
Оксин
12

Вы имеете в виду это?

var listOfList = new List<List<int>>() {
    new List<int>() { 1, 2 },
    new List<int>() { 3, 4 },
    new List<int>() { 5, 6 }
};
var list = new List<int> { 9, 9, 9 };
var result = list.Concat(listOfList.SelectMany(x => x));

foreach (var x in result) Console.WriteLine(x);

Результаты в: 9 9 9 1 2 3 4 5 6

IRBMe
источник
Или вы можете использовать list.AddRange () вместо Concat (), чтобы добавить объединенные элементы в существующий список.
dahlbyk
1

Для List<List<List<x>>>и так далее, используйте

list.SelectMany(x => x.SelectMany(y => y)).ToList();

Это было опубликовано в комментарии, но, на мой взгляд, заслуживает отдельного ответа.

Арман Макхитариан
источник