2012-02-09 16 views
5

Tengo una lista. Por razones válidas, duplico la Lista muchas veces y la uso para diferentes propósitos. En algún momento, necesito verificar si el contenido de todas estas colecciones es el mismo.cómo verificar el contenido de las colecciones (> 2) son las mismas

Bueno, sé cómo hacer esto. Pero como soy fanático de la codificación de "mano corta" (linq ...) me gustaría saber si puedo verificar esto de manera EFICAZ con la menor cantidad de líneas de código.

List<string> original, duplicate1, duplicate2, duplicate3, duplicate4 
             = new List<string(); 

     //...some code..... 
     bool isequal = duplicate4.sequenceequal(duplicate3) 
     && duplicate3.sequenceequal(duplicate2) 
     && duplicate2.sequenceequal(duplicate1) 
     && duplicate1.sequenceequal(original);//can we do it better than this 

ACTUALIZACIÓN

Codeinchaos señaló ciertas senarios que no he pensado (duplicados y el orden de la lista) .Aunque SequenceEqual se hará cargo de los duplicados del orden de la lista puede ser un problema. Así que estoy cambiando el código de la siguiente manera. Necesito copiar las Listas para esto.

List<List<string>> copy = new List<List<int>> { duplicate1, duplicate2, 
               duplicate3, duplicate4 }; 
bool iseqaul = (original.All(x => (copy.All(y => y.Remove(x)))) 
             && copy.All(n => n.Count == 0)); 

Update2

Gracias a Eric-utilizando un HashSet puede ser muy eficiente de la siguiente manera. Esto no cubrirá duplicados sin embargo.

List<HashSet<string>> copy2 =new List<HashSet<string>>{new HashSet<string>(duplicate1), 
                 new HashSet<string>(duplicate2), 
                 new HashSet<string> duplicate3), 
                 new HashSet<string>(duplicate4)}; 
    HashSet<string> origninalhashset = new HashSet<string>(original); 
    bool eq = copy2.All(x => origninalhashset.SetEquals(x)); 

Update3 Gracias a Eric - El código original de este post con SequenceEqual trabajará con la clasificación. Como Sequenceequal considerará el orden de las colecciones, las colecciones deben ordenarse antes de llamar a sequenceequal. Supongo que esto no es una gran probelma, ya que la clasificación es bastante rápida (nlogn).

UPDATE4 Según la sugerencia de Brian, puedo utilizar una búsqueda para esto.

var originallkup = original.ToLookup(i => i);  
var lookuplist = new List<ILookup<int, int>> 
            { duplicate4.ToLookup(i=> i), 
             duplicate3.ToLookup(i=> i), 
             duplicate2.ToLookup(i=> i), 
             duplicate1.ToLookup(i=> i) 
            }; 

bool isequal = (lookuplist.Sum(x => x.Count) == (originallkup.Count * 4)) &&  
    (originallkup.All(x => lookuplist.All(i => i[x.Key].Count() == x.Count()))); 

Gracias a todos por sus respuestas.

+1

¿Es importante el pedido? ¿O solo el contenido? – weston

+0

@ weston: solo el contenido es importante – Jimmy

+3

"Eficiencia" o "número de líneas de código más corto" Elija uno – weston

Respuesta

7

Tengo una lista. Duplico la lista muchas veces y la utilizo para diferentes propósitos.En algún momento, necesito verificar si el contenido de todas estas colecciones es el mismo.

Un comentarista entonces pregunta:

importante es el orden? ¿O solo el contenido?

y usted responde:

sólo el contenido es importante

En ese caso está utilizando la estructura de datos incorrecto en el primer lugar. Utilice HashSet<T>, no List<T>, para representar desordenada colección de artículos que deben ser comparados de forma económica para establecer la igualdad.

Una vez que tenga todo en conjuntos de hash en lugar de listas, puede simplemente usar su método SetEquals para ver si algún par de conjuntos es desigual.

Alternativamente: mantenga todo en las listas, hasta el punto en que desee comparar por igualdad. Inicialice un conjunto de hash de una de las listas, y luego use SetEquals para comparar ese hash en cada otra lista.

+0

@ Eric: tiene toda la razón. Mi única preocupación ahora son los duplicados (porque hashset no tomará duplicados) – Jimmy

+1

@Jimmy: utilice una clave de mapeo del diccionario para valorar. Tenga la llave sea el artículo y el valor sea un recuento. Para verificar que los contenidos sean los mismos, simplemente verifique si los diccionarios tienen una longitud coincidente (lo que le indicará un recuento de elementos distintos), luego, para cada clave en dict1, compruebe que 'dict2.TryGetValue (clave, conteo de saltos) && count == dict1 [tecla] '. – Brian

+0

@ Brian- si lo hago, tengo que escribir un contenedor y manejar duplicados como recuento en el diccionario cuando modifico elementos. No preferiría eso. – Jimmy

4

Sinceramente, no puedo pensar en una solución más eficiente, pero en cuanto a la reducción del número de líneas de código, dar a esto un golpe:

var allLists = new List<List<string>>() { original, duplicate1, duplicate2, duplicate3, duplicate4 }; 

bool allEqual = allLists.All(l => l.SequenceEqual(original)); 

O, utilice el operador Any - podría ser mejor en términos de rendimiento.

bool allEqual = !allLists.Any(l => !l.SequenceEqual(original)); 

EDIT: confirmada, Any se detendrá la enumeración de la fuente una vez que se determina un valor. Gracias MSDN.

EDIT # 2: He estado buscando el rendimiento de SequenceEquals. This guy tiene una buena publicación comparando SequenceEquals a una función más imperativa. Modifiqué su ejemplo para trabajar con List<string> y mis hallazgos coinciden con los suyos. Parece que, en lo que respecta al rendimiento, SequenceEquals no ocupa un lugar destacado en la lista de métodos preferidos.

+0

No estoy seguro de si 'SequenceEquals' tiene una referencia anticipada para la igualdad de referencia, pero de lo contrario, la comprobación manual hará que el código sea un poco más rápido. – CodesInChaos

+0

@CodeInChaos: Gracias, no pensé en una salida anticipada. Creo que 'Any' podría ser una mejor jugada en este caso. Ver mi respuesta editada. – tobias86

+1

No estaba hablando de este tipo de salida anticipada. Estoy seguro de que 'Todos' ya lo hace. Quise decir 'l => (objeto.ReferenceEquals (l, original) || l.SequenceEqual (original) '. Pero no estoy seguro si eso es necesario tampoco. – CodesInChaos

Cuestiones relacionadas