2012-05-21 9 views
8

Tengo una pregunta acerca de LINQ/Lambda y el problema siguiente:C# diccionarios intersectar

Tengo dos diccionarios, primaria y secundaria ... Estos dos diccionarios se definen como clave = cadena, Valor = int. Necesito recortar el diccionario principal si las TECLAS se cruzan con el diccionario secundario.

es decir:

primaryDict = ["thing1", 33] ["thing2", 24] ["thing3", 21] ["thing4", 17] ["thing5", 12] 

secondaryDict = ["thing1", 22] ["thing3", 20] ["thing4", 19] ["thing7", 17] ["thing9", 10] 

resultDict = ["thing1", 33] ["thing3", 21] ["thing4", 17] 

Mi intento:

resultDict = primaryDict.Keys.Intersect(secondaryDict.Keys).ToDictionary(t => t.Key, t.Value); 

Esto, obviamente, no funciona debido a que el primaryDict.Keys.Intersect está devolviendo una lista de claves ... ¿cómo iba a restablecer una nueva diccionario, o emparejar el diccionario principal? Cualquier ayuda sería apreciada.

Respuesta

17

Puede hacer de esta manera:

resultDict = primaryDict.Keys.Intersect(secondaryDict.Keys) 
           .ToDictionary(t => t, t => primaryDict[t]); 

o, alternativamente:

resultDict = primaryDict.Where(x => secondaryDict.ContainsKey(x.Key)) 
         .ToDictionary(x => x.Key, x => x.Value); 

este último tal vez es un poco más eficiente porque evita la creación de una colección de usar y tirar (el generado por el método Intersect) y no requiere de un segundo acceso por clave a primaryDict.

EDITAR (según el comentario):

resultDict = 
primaryDict.Where(x => secondaryDict.ContainsKey(x.Key)) 
      .ToDictionary(x => x.Key, x => x.Value + secondaryDict[x.Key]); 
+1

creo que la última versión es mucho mejor, ya que no creo que tratar el diccionario como un IEnumerable aprovechará el diccionario, y se ejecutarán en O (n) tiempo –

+0

Eso funcionó muy bien para lo que estoy haciendo ... Usé la segunda solución y todo está funcionando como se esperaba. ¡Rock, Dave! –

+0

Como seguimiento ... ¿es posible sumar los valores en esta misma expresión? –

2

No comprobado:

resultDict = primaryDict.Keys.Intersect(secondaryDict.Keys).ToDictionary(t => t.Key, primaryDict[t.Key]); 
3

Puede seguir utilizando primaryDict dentro de su declaración de LINQ, ya que está creando un nuevo diccionario , que sólo se asigna a la variable una vez que se crea:

resultDict = primaryDict.Keys 
         .Intersect(secondaryDict.Keys) 
         .ToDictionary(t => t, primaryDict[t]);