Gostaria de comparar o conteúdo de algumas coleções no meu método Equals. Eu tenho um dicionário e um IList. Existe um método interno para fazer isso?
Editado: quero comparar dois dicionários e duas ILists, então acho que o que significa igualdade é claro - se os dois dicionários contêm as mesmas chaves mapeadas para os mesmos valores, então são iguais.
c#
.net
collections
TimK
fonte
fonte
IList
? A pergunta é ambígua.Enumerable.SequenceEqual
eISet.SetEquals
forneça versões dessa funcionalidade. Se você quer ser independente de pedidos e trabalhar com coleções com duplicatas, precisará fazer o seu próprio. Confira a implementação sugerida neste postRespostas:
Enumerable.SequenceEqual
Você não pode comparar diretamente a lista e o dicionário, mas pode comparar a lista de valores do Dicionário com a lista
fonte
.Keys
e.Values
pode retornar as chaves e valores em qualquer ordem eles se sentem como, e que a ordem é provável que a mudança como o dicionário é modificado também. Eu sugiro que você leia o que é um dicionário e o que não é.Como outros sugeriram e observaram,
SequenceEqual
é sensível à ordem. Para resolver isso, você pode classificar o dicionário por chave (que é única e, portanto, a classificação é sempre estável) e usarSequenceEqual
. A expressão a seguir verifica se dois dicionários são iguais, independentemente de sua ordem interna:Edição: Como apontado por Jeppe Stig Nielsen, alguns objetos têm um
IComparer<T>
que é incompatível com seusIEqualityComparer<T>
, produzindo resultados incorretos. Ao usar chaves com esse objeto, você deve especificar um corretoIComparer<T>
para essas chaves. Por exemplo, com chaves de seqüência de caracteres (que apresentam esse problema), você deve fazer o seguinte para obter resultados corretos:fonte
CompareTo
? Sua solução vai explodir então. E se o tipo de chave tiver um comparador padrão incompatível com seu comparador de igualdade padrão? Este é o casostring
, você sabe. Como exemplo destes dicionários (com comparadores de igualdade padrão implícitos) irá falhar seu teste (sob todas as informações sobre cultura que conheço):var dictionary1 = new Dictionary<string, int> { { "Strasse", 10 }, { "Straße", 20 }, }; var dictionary2 = new Dictionary<string, int> { { "Straße", 20 }, { "Strasse", 10 }, };
IComparer
eIEqualityComparer
- eu não estava ciente desse problema, muito interessante! Atualizei a resposta com uma possível solução. Sobre a falta deCompareTo
, acho que o desenvolvedor deve garantir que o delegado fornecido aoOrderBy()
método retorne algo comparável. Eu acho que isso é verdade para qualquer uso ouOrderBy()
mesmo fora das comparações de dicionário.Além do SequenceEqual mencionado , que
(que pode ser o comparador padrão, ou seja, um substituto
Equals()
)vale ressaltar que em .Net4 há SetEquals em
ISet
objetos, o quePortanto, se você deseja ter uma lista de objetos, mas eles não precisam estar em uma ordem específica, considere que um
ISet
(como aHashSet
) pode ser a escolha certa.fonte
Dê uma olhada no método Enumerable.SequenceEqual
fonte
.NET Não possui nenhuma ferramenta poderosa para comparar coleções. Eu desenvolvi uma solução simples que você pode encontrar no link abaixo:
http://robertbouillon.com/2010/04/29/comparing-collections-in-net/
Isso executará uma comparação de igualdade, independentemente da ordem:
Isso verificará se os itens foram adicionados / removidos:
Você verá quais itens do dicionário foram alterados:
fonte
.Removed
é o mesmo quelist1.Except(list2)
,.Added
élist2.Except(list1)
,.Equal
élist1.Intersect(list2)
e.Different
éoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => left.Value == right.Value)
. Você pode fazer quase qualquer comparação com o LINQ..Different
éoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => new { Key = left.Key, NewValue = right.Value, Different = left.Value == right.Value).Where(d => d.Different)
. E você pode até adicionarOldValue = left.Value
se precisar do valor antigo também.Eu não sabia sobre o método Enumerable.SequenceEqual (você aprende algo todos os dias ...), mas sugeria usar um método de extensão; algo assim:
Curiosamente, depois de levar 2 segundos para ler sobre o SequenceEqual, parece que a Microsoft criou a função que descrevi para você.
fonte
Isso não está respondendo diretamente às suas perguntas, mas o TestTools e o NUnit da MS fornecem
o que faz praticamente o que você deseja.
fonte
Para comparar coleções, você também pode usar o LINQ.
Enumerable.Intersect
retorna todos os pares que são iguais. Você pode comparar dois dicionários como este:A primeira comparação é necessária porque
dict2
pode conter todas as chaves dedict1
e mais.Você também pode usar pensar em variações usando
Enumerable.Except
eEnumerable.Union
que levam a resultados semelhantes. Mas pode ser usado para determinar as diferenças exatas entre os conjuntos.fonte
Que tal este exemplo:
Cortesia: https://www.dotnetperls.com/dictionary-equals
fonte
Para coleções ordenadas (lista, matriz), use
SequenceEqual
para uso com HashSet
SetEquals
para o Dictionary, você pode fazer:
(Uma solução mais otimizada usará a classificação, mas isso exigirá
IComparable<TValue>
)fonte
Não. A estrutura de coleta não tem nenhum conceito de igualdade. Se você pensar bem, não há como comparar coleções que não são subjetivas. Por exemplo, comparando seu IList ao seu Dicionário, eles seriam iguais se todas as chaves estivessem no IList, todos os valores estivessem no IList ou se ambos estivessem no IList? Não há uma maneira óbvia de comparar essas duas coleções sem o conhecimento do que elas devem ser usadas, de modo que um método igual para uso geral não faz sentido.
fonte
Não, porque a estrutura não sabe como comparar o conteúdo de suas listas.
Veja isso:
http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx
fonte
IComparer<T>
, Substituindoobject.Equals
,IEquatable<T>
,IComparable<T>
...fonte
Não havia, não existe e pode não haver, pelo menos eu acredito que sim. A razão por trás da igualdade de coleção é provavelmente um comportamento definido pelo usuário.
Os elementos das coleções não devem estar em uma ordem específica, embora tenham uma ordem natural, não é nisso que os algoritmos de comparação devem confiar. Digamos que você tenha duas coleções de:
Eles são iguais ou não? Você deve saber, mas eu não sei qual é o seu ponto de vista.
Coleções são conceitualmente desordenadas por padrão, até que os algoritmos forneçam as regras de classificação. A mesma coisa que o SQL Server chamará a atenção é quando você tenta fazer paginação, requer que você forneça regras de classificação:
https://docs.microsoft.com/pt-BR/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017
Mais duas coleções:
Novamente, eles são iguais ou não? Diz-me tu ..
A repetibilidade de elementos de uma coleção desempenha seu papel em diferentes cenários e algumas coleções, como
Dictionary<TKey, TValue>
nem mesmo permitem elementos repetidos.Acredito que esses tipos de igualdade são definidos por aplicativos e, portanto, a estrutura não forneceu todas as implementações possíveis.
Bem, em casos gerais,
Enumerable.SequenceEqual
é bom o suficiente, mas retorna falso no seguinte caso:Eu li algumas respostas para perguntas como essa (você pode pesquisar no Google por elas) e o que eu usaria, em geral:
Isso significa que uma coleção representa a outra em seus elementos, incluindo tempos repetidos sem levar em consideração o pedido original. Algumas notas da implementação:
GetHashCode()
é apenas para ordenar, não para igualdade; Eu acho que é suficiente neste casoCount()
realmente não enumera a coleção e se enquadra diretamente na implementação da propriedadeICollection<T>.Count
Se as referências são iguais, é apenas Boris
fonte