Eu tenho a seguinte situação
class Person
{
string Name;
int Value;
int Change;
}
List<Person> list1;
List<Person> list2;
Eu preciso combinar as 2 listas em uma nova List<Person>
, caso seja a mesma pessoa que o registro de combinação teria esse nome, valor da pessoa na lista2, a mudança seria o valor da lista2 - o valor da lista1. A mudança é 0 se não houver duplicado
Respostas:
Isso pode ser feito facilmente usando o método de extensão Linq Union. Por exemplo:
Isso retornará uma lista na qual as duas listas são mescladas e as duplas são removidas. Se você não especificar um comparador no método de extensão Union, como no meu exemplo, ele usará os métodos Equals e GetHashCode padrão na sua classe Person. Se, por exemplo, você deseja comparar pessoas, comparando a propriedade Name, você deve substituir esses métodos para realizar a comparação sozinho. Verifique o seguinte exemplo de código para fazer isso. Você deve adicionar esse código à sua classe Person.
Se você não quiser definir o método Equals padrão da sua classe Person para sempre usar o Name para comparar dois objetos, também poderá escrever uma classe comparadora que use a interface IEqualityComparer. Você pode fornecer esse comparador como o segundo parâmetro no método Union da extensão Linq. Mais informações sobre como escrever esse método comparador podem ser encontradas em http://msdn.microsoft.com/en-us/library/system.collections.iequalitycomparer.aspx
fonte
Union
comIntersect
?Concat
que não mesclar duplicatasPercebi que essa pergunta não foi marcada como respondida após 2 anos - acho que a resposta mais próxima é Richards, mas pode ser bastante simplificada para isso:
Embora isso não ocorra erros no caso em que você tem nomes duplicados em qualquer um dos conjuntos.
Algumas outras respostas sugeriram o uso da união - esse definitivamente não é o caminho a seguir, pois você apenas obterá uma lista distinta, sem fazer a combinação.
fonte
Por que você não usa apenas
Concat
?O Concat faz parte do linq e é mais eficiente do que fazer um
AddRange()
no seu caso:
fonte
Actually, due to deferred execution, using Concat would likely be faster because it avoids object allocation - Concat doesn't copy anything, it just creates links between the lists so when enumerating and you reach the end of one it transparently takes you to the start of the next!
Este é o meu ponto.Este é o Linq
Esta é Normaly (AddRange)
Esta é Normaly (Foreach)
Esta é Normaly (Foreach-Dublice)
fonte
Existem algumas partes para fazer isso, supondo que cada lista não contenha duplicatas, Name seja um identificador exclusivo e nenhuma lista seja ordenada.
Primeiro, crie um método de extensão de acréscimo para obter uma única lista:
Assim, pode obter uma única lista:
Em seguida, agrupe no nome
Em seguida, pode processar cada grupo com um auxiliar para processar um grupo de cada vez
Que pode ser aplicado a cada elemento de
grouped
:(Aviso: não testado.)
fonte
Append
é uma duplicata quase exata da pronta entregaConcat
.Enumerable.Concat
e, portanto, re-implementando-o.Você precisa de algo como uma junção externa completa. System.Linq.Enumerable não possui um método que implemente uma associação externa completa; portanto, precisamos fazer isso sozinhos.
fonte
O código a seguir funciona para o seu problema? Eu usei um foreach com um pouco de linq dentro para fazer a combinação de listas e assumi que as pessoas são iguais se seus nomes corresponderem, e parece imprimir os valores esperados quando executados. O Resharper não oferece sugestões para converter o foreach em linq, portanto, provavelmente é tão bom quanto possível.
fonte
fonte