¿Cómo fusionar una lista de listas con el mismo tipo de elementos en una sola lista de elementos?

210

La pregunta es confusa, pero es mucho más clara como se describe en los siguientes códigos:

   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 = ???

¿No está seguro si es posible usando C # LINQ o Lambda?

Básicamente, ¿cómo puedo concatenar o " aplanar " una lista de listas?

David.Chu.ca
fuente

Respuestas:

456

Use el método de extensión SelectMany

list = listOfList.SelectMany(x => x).ToList();
JaredPar
fuente
73
Me pregunto cuántas personas han escrito su propia extensión "Flatten" sin darse cuenta de cómo funciona SelectMany.
James Schek el
1
¿Por qué se necesita x => x para que esto funcione? Normalmente veo cosas como x => x +1 pero no x => x.
SwimBikeRun
9
@SwimBikeRun SelectMany se usa para tomar un IEnumerable de TSources, convertir cada TSource en la lista en un IEnumerable de TResults, luego concatenar todos esos IEnumerables en uno grande. En este caso, tiene una lista de listas para comenzar, por lo que si desea concatenarlas, la función para asignar desde un TSource (que es un IEnumerable de TResults) a un IEnumerable of TResults es la función de identidad (x => x). Este es realmente un caso especial en el que no necesita el paso adicional de convertir cada TSource en una lista, porque ya es una lista.
Sean
@JaredPar, ¿podemos aplicar esta lógica a la lista <lista <lista <T> >>?
Tk1993
44
@TusharKukreti Claro, solo uselist.SelectMany(x => x.SelectMany(y => y)).ToList();
Brandon Kramer
13

Aquí está la versión de sintaxis integrada de C #:

var items =
    from list in listOfList
    from item in list
    select item;
Joe Chung
fuente
Un poco confuso, pero agradable. ¿Cómo esto? var items = from item in (from list in listOflist seleccionar lista) seleccionar elemento
David.Chu.ca
44
El 'doble de' es el mismo que SelectMany ... SelectMany es probablemente el más poderoso de los métodos LINQ (u operadores de consulta). Para ver por qué, Google "LINQ SelectMany Monad" y descubrirá más de lo que querrá saber al respecto.
Richard Anthony Hein
3
No incluya las citas cuando busque en Google "LINQ SelectMany Monad" o simplemente lo dirigirá de regreso a aquí.
Oxin
12

¿Quieres decir esto?

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);

Resultados en: 9 9 9 1 2 3 4 5 6

IRBMe
fuente
O puede usar list.AddRange () en lugar de Concat () para agregar los elementos combinados a la lista existente.
dahlbyk
1

Para List<List<List<x>>>y así sucesivamente, use

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

Esto ha sido publicado en un comentario, pero merece una respuesta por separado en mi opinión.

Arman McHitarian
fuente