Digamos que eu tenha um número arbitrário de coleções, cada uma contendo objetos do mesmo tipo (por exemplo, List<int> foo
e List<int> bar
). Se essas coleções estivessem em uma coleção (por exemplo, do tipo List<List<int>>
, eu poderia usar SelectMany
para combiná-las todas em uma coleção.
No entanto, se essas coleções ainda não estiverem na mesma coleção, tenho a impressão de que teria que escrever um método como este:
public static IEnumerable<T> Combine<T>(params ICollection<T>[] toCombine)
{
return toCombine.SelectMany(x => x);
}
Que eu então chamaria assim:
var combined = Combine(foo, bar);
Existe uma maneira limpa e elegante de combinar (qualquer número de) coleções sem ter que escrever um método utilitário como o Combine
acima? Parece simples o suficiente para que haja uma maneira de fazer isso no LINQ, mas talvez não.
c#
linq
generics
collections
Rosquinha
fonte
fonte
Respostas:
Eu acho que você pode estar procurando LINQ
.Concat()
?Alternativamente,
.Union()
irá remover elementos duplicados.fonte
.Union()
dica. Tenha em mente que você precisará implementar IComparer em seu tipo personalizado, caso seja.Para mim,
Concat
como um método de extensão, não é muito elegante em meu código quando tenho várias sequências grandes para concat. Este é apenas um problema de recuo / formatação de código e algo muito pessoal.Claro que fica bem assim:
Não é tão legível quando se lê como:
Ou quando parece:
ou qualquer que seja sua formatação preferida. As coisas pioram com concats mais complexos. A razão para meu tipo de dissonância cognitiva com o estilo acima é que a primeira sequência está fora do
Concat
método, enquanto as sequências subsequentes estão dentro. Prefiro chamar oConcat
método estático diretamente e não o estilo de extensão:Para mais número de concats de sequências, carrego o mesmo método estático do OP:
Então posso escrever:
Parece melhor. O nome de classe extra, caso contrário redundante, que tenho que escrever não é um problema para mim, considerando que minhas sequências parecem mais claras com a
Concat
chamada. É um problema menor em C # 6 . Você pode apenas escrever:Gostaríamos de ter operadores de concatenação de lista em C #, algo como:
Muito mais limpo assim.
fonte
Where
,OrderBy
) primeiro para maior clareza, especialmente se elas forem mais complexas do que este exemplo.Para o caso quando você faz tem uma coleção de coleções, ou seja, um
List<List<T>>
,Enumerable.Aggregate
é uma maneira mais elegante para combinar todas as listas em um:fonte
lists
aqui primeiro? Esse é o primeiro problema que o OP tem. Se ele tivesse umcollection<collection>
para começar, entãoSelectMany
é muito mais simples.Use
Enumerable.Concat
assim:fonte
Use
Enumerable.Concact
:fonte
Você sempre pode usar Aggregate combinado com Concat ...
fonte
SelectMany
é apenas mais simples.A única maneira que vejo é usar
Concat()
Mas você deve decidir o que é melhor:
ou
Um ponto por
Concat()
que será uma escolha melhor é que será mais óbvio para outro desenvolvedor. Mais legível e simples.fonte
Você pode usar o Union da seguinte maneira:
Isso removerá elementos idênticos, portanto, se você os tiver, pode querer usá-los
Concat
.fonte
Enumerable.Union
é uma união de conjuntos que não produz o resultado desejado (produz duplicatas apenas uma vez).int
no meu exemplo pode ter confundido um pouco as pessoas; masUnion
não funcionará para mim neste caso.Algumas técnicas usando inicializadores de coleção -
assumindo essas listas:
SelectMany
com um inicializador de array (não muito elegante para mim, mas não depende de nenhuma função auxiliar):Defina uma extensão de lista para Adicionar que permite
IEnumerable<T>
noList<T>
inicializador :Em seguida, você pode criar uma nova lista contendo os elementos dos outros como esta (também permite que itens individuais sejam misturados).
fonte
Considerando que você está começando com um monte de coleções separadas, acho que sua solução é bastante elegante. Você vai ter que fazer algo para costurá-los juntos.
Seria mais conveniente sintaticamente fazer um método de extensão de seu método Combine, que o tornaria disponível em qualquer lugar que você fosse.
fonte
Tudo que você precisa é isso, para qualquer
IEnumerable<IEnumerable<T>> lists
:Isso combinará todos os itens em
lists
umIEnumerable<T>
(com duplicatas). Use emUnion
vez deConcat
para remover duplicatas, conforme observado nas outras respostas.fonte