Me gustaría comparar el contenido de un par de colecciones en mi método Equals. Tengo un diccionario y una lista IL. ¿Hay un método incorporado para hacer esto?
Editado: Quiero comparar dos Diccionarios y dos IListas, por lo que creo que lo que significa igualdad está claro: si los dos diccionarios contienen las mismas claves asignadas a los mismos valores, entonces son iguales.
c#
.net
collections
TimK
fuente
fuente
IList
? La pregunta es ambigua.Enumerable.SequenceEqual
yISet.SetEquals
proporcionar versiones de esta funcionalidad. Si desea ser independiente de los pedidos y trabajar con colecciones que tienen duplicados, deberá rodar los suyos. Echa un vistazo a la implementación sugerida en esta publicaciónRespuestas:
Enumerable.SequenceEqual
No puede comparar directamente la lista y el diccionario, pero puede comparar la lista de valores del Diccionario con la lista
fuente
.Keys
y.Values
puede devolver las claves y valores en cualquier orden que se sienten como, y que el orden es probable que el cambio como el diccionario se modifica también. Le sugiero que lea sobre qué es un diccionario y qué no es.Como otros han sugerido y han notado,
SequenceEqual
es sensible al orden. Para resolver eso, puede ordenar el diccionario por clave (que es único y, por lo tanto, el orden siempre es estable) y luego usarloSequenceEqual
. La siguiente expresión verifica si dos diccionarios son iguales independientemente de su orden interno:EDITAR: Como señaló Jeppe Stig Nielsen, algunos objetos tienen un
IComparer<T>
incompatible con ellosIEqualityComparer<T>
, lo que arroja resultados incorrectos. Cuando utilice claves con dicho objeto, debe especificar una correctaIComparer<T>
para esas claves. Por ejemplo, con las claves de cadena (que exhiben este problema), debe hacer lo siguiente para obtener resultados correctos:fuente
CompareTo
? Su solución explotará entonces. ¿Y si el tipo de clave tiene un comparador predeterminado que es incompatible con su comparador de igualdad predeterminado? Este es el casostring
, ya sabes. Como ejemplo, estos diccionarios (con comparadores de igualdad implícitos predeterminados) no pasarán la prueba (según todas las informaciones culturales que conozco):var dictionary1 = new Dictionary<string, int> { { "Strasse", 10 }, { "Straße", 20 }, }; var dictionary2 = new Dictionary<string, int> { { "Straße", 20 }, { "Strasse", 10 }, };
IComparer
yIEqualityComparer
- No estaba al tanto de este problema, ¡muy interesante! Actualicé la respuesta con una posible solución. Sobre la falta deCompareTo
, creo que el desarrollador debe asegurarse de que el delegado proporcionado alOrderBy()
método devuelva algo comparable. Creo que esto es cierto para cualquier uso oOrderBy()
, incluso fuera de las comparaciones de diccionario.Además del mencionado SequenceEqual , que
(que puede ser el comparador predeterminado, es decir, una anulación
Equals()
)Vale la pena mencionar que en .Net4 hay SetEquals en los
ISet
objetos, queEntonces, si desea tener una lista de objetos, pero no es necesario que estén en un orden específico, considere que un
ISet
(como aHashSet
) puede ser la opción correcta.fuente
Eche un vistazo al método Enumerable.SequenceEqual
fuente
.NET carece de herramientas poderosas para comparar colecciones. He desarrollado una solución simple que puede encontrar en el siguiente enlace:
http://robertbouillon.com/2010/04/29/comparing-collections-in-net/
Esto realizará una comparación de igualdad independientemente del orden:
Esto verificará si se agregaron / eliminaron elementos:
Esto verá qué elementos del diccionario cambiaron:
fuente
.Removed
es lo mismo quelist1.Except(list2)
,.Added
eslist2.Except(list1)
,.Equal
eslist1.Intersect(list2)
y.Different
esoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => left.Value == right.Value)
. Puedes hacer casi cualquier comparación con LINQ..Different
esoriginal.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 incluso puede agregarOldValue = left.Value
si necesita el valor anterior también.No sabía sobre el método Enumerable.SequenceEqual (aprendes algo todos los días ...), pero iba a sugerir usar un método de extensión; algo como esto:
Curiosamente, después de tomar 2 segundos para leer sobre SequenceEqual, parece que Microsoft ha desarrollado la función que le describí.
fuente
Esto no responde directamente a sus preguntas, pero tanto TestTools de MS como NUnit proporcionan
que hace más o menos lo que quieres.
fuente
Para comparar colecciones, también puede usar LINQ.
Enumerable.Intersect
devuelve todos los pares que son iguales. Puede comparar dos diccionarios como este:La primera comparación es necesaria porque
dict2
puede contener todas las clavesdict1
y más.También puede usar pensar en variaciones usando
Enumerable.Except
yEnumerable.Union
que conducen a resultados similares. Pero se puede usar para determinar las diferencias exactas entre conjuntos.fuente
¿Qué tal este ejemplo?
Cortesía: https://www.dotnetperls.com/dictionary-equals
fuente
Para colecciones ordenadas (List, Array) use
SequenceEqual
para uso de HashSet
SetEquals
para Diccionario puedes hacer:
(Una solución más optimizada utilizará la clasificación, pero eso requerirá
IComparable<TValue>
)fuente
No. El marco de la colección no tiene ningún concepto de igualdad. Si lo piensa, no hay forma de comparar colecciones que no sean subjetivas. Por ejemplo, si compara su IList con su Diccionario, ¿serían iguales si todas las claves estuvieran en la IList, todos los valores estuvieran en la IList o si ambas estuvieran en la IList? No hay una forma obvia de comparar estas dos colecciones sin saber para qué se utilizarán, por lo que no tiene sentido un método igual de propósito general.
fuente
No, porque el marco no sabe cómo comparar el contenido de sus listas.
Echa un vistazo a esto:
http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx
fuente
IComparer<T>
, Anulandoobject.Equals
,IEquatable<T>
,IComparable<T>
...fuente
No hubo, no es y podría no ser, al menos eso creo. La razón detrás de esto es la igualdad de colección es probablemente un comportamiento definido por el usuario.
Se supone que los elementos en las colecciones no están en un orden particular, aunque sí tienen un orden natural, no es en lo que deben confiar los algoritmos de comparación. Digamos que tiene dos colecciones de:
¿Son iguales o no? Debes saber pero no sé cuál es tu punto de vista.
Las colecciones están conceptualmente desordenadas de forma predeterminada, hasta que los algoritmos proporcionan las reglas de clasificación. Lo mismo que SQL Server le llamará la atención es que cuando intenta hacer paginación, requiere que proporcione reglas de clasificación:
https://docs.microsoft.com/en-US/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017
Otras dos colecciones más:
De nuevo, ¿son iguales o no? Dígame usted ..
La repetibilidad de elementos de una colección juega su papel en diferentes escenarios y algunas colecciones como
Dictionary<TKey, TValue>
ni siquiera permiten elementos repetidos.Creo que este tipo de igualdad está definida por la aplicación y, por lo tanto, el marco no proporcionó todas las implementaciones posibles.
Bueno, en casos generales
Enumerable.SequenceEqual
es lo suficientemente bueno pero devuelve falso en el siguiente caso:Leí algunas respuestas a preguntas como esta (puede buscarlas en Google ) y lo que usaría, en general:
Eso significa que una colección representa a la otra en sus elementos, incluidos los tiempos repetidos sin tener en cuenta el pedido original. Algunas notas de la implementación:
GetHashCode()
es solo para ordenar, no para la igualdad; Creo que es suficiente en este casoCount()
realmente no enumera la colección y cae directamente en la implementación de propiedad deICollection<T>.Count
Si las referencias son iguales, es solo Boris
fuente