2010-09-21 49 views
6

Sé que LINQ tiene un método SequenceEquals. Este método asegura que el valor de cada artículo en cada colección coincida, en el mismo orden.¿Hay un método equivalente LINQ?

Lo que estoy buscando es un tipo más de funcionalidad "Equivalente". Solo que ambas secuencias contienen los mismos elementos, no necesariamente en el mismo orden. Por ejemplo, nUnit tiene CollectionAssert.AreEqual() y CollectionAssert.AreEquivalent() que hacen lo que estoy explicando.

Sé que puedo hacer esto ya sea por:

  1. ordenar las listas antes de tiempo y utilizando SequenceEquals
  2. Usando Intersect, luego ver si la intersección es igual a la secuencia original.

Ejemplo:

var source = new[] {5, 6, 7}; 
source.Intersect(new[] {5, 7, 6}).Count() == source.Length; 
+1

Hay un error en el ejemplo de respuesta. Debe compararlo con ambos conteos, de lo contrario su función devolvería 'verdadera' cuando la fuente es un subconjunto del objetivo. Es decir. fuente {5,6} y destino {5,7,6} – cellik

Respuesta

8

Crearía un método de extensión que hace la intersección y luego compara los recuentos.

+0

Obtienes la respuesta para dándome la idea de comparar los recuentos, por lo que fue agradable y compacto, ¡gracias! Se ve así: var source = new [] {5, 6, 7}; source.Intersect (new [] {5, 7, 6}). Count() == source.Length; – CubanX

+0

@CubanX: Tenga en cuenta que si la fuente contiene algún duplicado, incluso 'source.SetEquals (source)' devolverá falso. –

+0

@Jon Buen punto, podría tener que lanzar un distintivo para garantizar que eso no ocurra. – CubanX

9

Se puede construir un conjunto y luego usar HashSet<T>.SetEquals. No está estrictamente dentro de LINQ, pero funciona muy bien con él :)

Por supuesto, puede escribir fácilmente su propio método de extensión para extender esto. Algo como esto:

public static bool SetEquals<T>(this IEnumerable<T> source, IEnumerable<T> other) 
{ 
    HashSet<T> hashSet = new HashSet<T>(source); 
    return hashSet.SetEquals(other); // Doesn't recurse! Calls HashSet.SetEquals 
} 

EDIT: Como se señaló en los comentarios, esto ignora el número de veces que se producen los elementos, así como el ordenamiento - por lo { 1, 2 } habría "iguala" a { 1, 2, 1, 2, 1, 1, 1 }. Si eso no es lo que quieres, se volverá un poco más complicado.

+0

por lo que 1,2 sería "igual" a 1,1,1,2,2,2? – spender

+0

@spender: para la igualdad * set *, eso es correcto. El conjunto de elementos en cada colección es el mismo. Sin embargo, vale la pena destacar, editará. –

+0

Jon, a veces en métodos como este, no puedo decidir si escribirlo como lo tienes o hacer algo como 'HashSet hashSet = source como HashSet ?? nuevo HashSet (fuente); '* potencialmente * guardando el costo de construir un nuevo' HashSet '. ¿Tienes una opinión sobre eso? –

2

lo hice de esta manera:

public static bool SetEquivalent<T>(
    this IEnumerable<T> aSet, 
    IEnumerable<T> anotherSet) 
{ 
    var diffA = aSet.Except(anotherSet).Count(); 
    var diffB = anotherSet.Except(aSet).Count(); 
    return diffA == diffB && diffA == 0; 
} 
Cuestiones relacionadas