Digamos que tengo un número arbitrario de colecciones, cada una con objetos del mismo tipo (por ejemplo, List<int> foo
y List<int> bar
). Si estas colecciones estuvieran en una colección (por ejemplo, de tipo List<List<int>>
, podría usar SelectMany
para combinarlas todas en una colección.
Sin embargo, si estas colecciones no están ya en la misma colección, tengo la impresión de que tendría que escribir un método como este:
public static IEnumerable<T> Combine<T>(params ICollection<T>[] toCombine)
{
return toCombine.SelectMany(x => x);
}
Que luego llamaría así:
var combined = Combine(foo, bar);
¿Existe una forma limpia y elegante de combinar (cualquier número de) colecciones sin tener que escribir un método de utilidad como el Combine
anterior? Parece bastante simple que debería haber una forma de hacerlo en LINQ, pero tal vez no.
c#
linq
generics
collections
Rosquilla
fuente
fuente
Respuestas:
Creo que podrías estar buscando LINQ's
.Concat()
.Alternativamente,
.Union()
eliminará elementos duplicados.fuente
.Union()
dato. Tenga en cuenta que deberá implementar IComparer en su tipo personalizado en caso de que lo sea.A mi
Concat
como método de extensión, no es muy elegante en mi código cuando tengo varias secuencias grandes para concatizar. Esto es simplemente un problema de formato / sangría de codificación y algo muy personal.Seguro que se ve bien así:
No es tan legible cuando se lee como:
O cuando parece:
o cualquiera que sea su formato preferido. Las cosas empeoran con concats más complejos. La razón de mi tipo de disonancia cognitiva con el estilo anterior es que la primera secuencia se encuentra fuera del
Concat
método, mientras que las secuencias posteriores se encuentran dentro. Prefiero llamar alConcat
método estático directamente y no al estilo de extensión:Para más cantidad de concats de secuencias, llevo el mismo método estático que en OP:
Entonces puedo escribir:
Se ve mejor. El nombre de clase adicional, por lo demás redundante, que tengo que escribir no es un problema para mí, considerando que mis secuencias se ven más limpias con la
Concat
llamada. Es un problema menor en C # 6 . Puedes simplemente escribir:Ojalá tuviéramos operadores de concatenación de listas en C #, algo como:
Mucho más limpio de esa manera.
fuente
Where
,OrderBy
) primero para mayor claridad, especialmente si son algo más complejas que este ejemplo.Para el caso en el que hacer tener una colección de colecciones, es decir una
List<List<T>>
,Enumerable.Aggregate
es una forma más elegante para combinar todas las listas en una sola:fuente
lists
aquí primero? Ese es el primer problema que tiene OP. Si tuviera unacollection<collection>
para empezar, entoncesSelectMany
es mucho más simple.Use
Enumerable.Concat
así:fuente
Utilizar
Enumerable.Concact
:fuente
Siempre puede usar Aggregate combinado con Concat ...
fuente
SelectMany
es simplemente más simple.La única forma que veo es usar
Concat()
Pero debes decidir qué es mejor:
o
Un punto por el
Concat()
que será una mejor opción es que será más obvio para otro desarrollador. Más legible y simple.fuente
Puede utilizar Union de la siguiente manera:
Sin embargo, esto eliminará elementos idénticos, por lo que si los tiene, es posible que desee usarlos en su
Concat
lugar.fuente
Enumerable.Union
es una unión de conjuntos que no produce el resultado deseado (solo produce duplicados una vez).int
en mi ejemplo podría haber desconcertado un poco a la gente; peroUnion
no funcionará para mí en este caso.Un par de técnicas que utilizan los inicializadores de colección:
asumiendo estas listas:
SelectMany
con un inicializador de matriz (no es realmente tan elegante para mí, pero no depende de ninguna función auxiliar):Defina una extensión de lista para Agregar que permita
IEnumerable<T>
en elList<T>
inicializador :Luego puede crear una nueva lista que contenga los elementos de los demás como este (también permite que se mezclen elementos individuales).
fuente
Dado que está comenzando con un montón de colecciones separadas, creo que su solución es bastante elegante. Vas a tener que hacer algo para unirlos.
Sintácticamente, sería más conveniente crear un método de extensión a partir de su método Combine, lo que lo haría disponible en cualquier lugar al que vaya.
fuente
Todo lo que necesita es esto, para cualquier
IEnumerable<IEnumerable<T>> lists
:Esto combinará todos los elementos en
lists
unoIEnumerable<T>
(con duplicados). Úselo enUnion
lugar deConcat
para eliminar duplicados, como se indica en las otras respuestas.fuente