2012-01-13 12 views
11

¿Hay un método LINQ para encontrar la diferencia entre dos diccionarios genéricos?
Igual que en this question, pero con diccionarios genéricos.encontrar la diferencia entre dos diccionarios

+0

Usted puede usar 'AsEnumerable' "convertir" a su diccionario en un' IEnumerable ', y luego usar la solución sugerida en la cuestión vinculada. Como KeyValuePair es una estructura, debe comparar por valor. – Heinzi

+1

No necesita 'AsEnumerable', ya que no tiene absolutamente ninguna conversión. Solo es un método conveniente limitar los métodos intellisense a las extensiones 'IEnumerable ' y permitir el uso de las extensiones 'IEnumerable ' en objetos que también implementan 'IQueryable ' sin necesidad de conversión. – Nuffin

+2

'dic1.Except (x => dic2.Contains (x)). Union (dic2.Except (x => dic1.Contais (X));', ¿quieres mejor método? –

Respuesta

21
var diff = dicOne.Except(dicTwo).Concat(dicTwo.Except(dicOne)); 
+1

¿este método compara solo las claves? –

+2

@ bto.rdz No, tanto la clave como el valor. – Magnus

+0

Excelente pero no te olvides de verificar 'null's –

0

algo como esto?

var dicOne = new Dictionary<string, string>(){ {"asdf", "asdf"}, {"few","faew"}}; 
var dicTwo = new Dictionary<string, string>(){ {"asdf", "asdf"}}; 

var unContained = dicOne.Where(x => !dicTwo.Contains(x)); 
+2

No incluye esos elementos solo en' dictTwo' pero no en 'dictOne'. –

1

Si el rendimiento es importante, es posible que desee utilizar la búsqueda de hash de la clase Dictionary y obtener una mejora de la velocidad. Tomé un escenario de prueba de un diccionario con 1 millón de entradas, lo copié profundamente y realicé 10 ediciones (5 entradas eliminadas, 5 agregadas) a la copia. [Tenía una tarea que hacer implicaba buscar cambios en los datos, y luego presionar solo los cambios a otra función.]

Con LINQ (ver la respuesta de Magnus) el tiempo transcurrido según el cronómetro fue de 3600ms aprox. Con la comparación simple usando Dictionary.Contains(), el tiempo transcurrido fue 600ms aprox. El entorno era Visual Studio 2017 Community en el modo de depuración para un arnés de prueba ConsoleApp, en la misma máquina.

Su kilometraje puede variar, y es posible que tenga un número modesto de líneas, por lo que puede no importar, pero para los diccionarios más grandes vale la pena utilizar la funcionalidad de búsqueda de la clase de diccionario.

public static void DiffDictionaries<T, U>(
     Dictionary<T, U> dicA, 
     Dictionary<T, U> dicB, 
     Dictionary<T, U> dicAdd, 
     Dictionary<T, U> dicDel) 
    { 
     // dicDel has entries that are in A, but not in B, 
     // ie they were deleted when moving from A to B 
     diffDicSub<T, U>(dicA, dicB, dicDel); 

     // dicAdd has entries that are in B, but not in A, 
     // ie they were added when moving from A to B 
     diffDicSub<T, U>(dicB, dicA, dicAdd); 
    } 

    private static void diffDicSub<T, U>(
     Dictionary<T, U> dicA, 
     Dictionary<T, U> dicB, 
     Dictionary<T, U> dicAExceptB) 
    { 
     // Walk A, and if any of the entries are not 
     // in B, add them to the result dictionary. 

     foreach (KeyValuePair<T, U> kvp in dicA) 
     { 
      if (!dicB.Contains(kvp)) 
      { 
       dicAExceptB[kvp.Key] = kvp.Value; 
      } 
     } 
    } 
Cuestiones relacionadas