2012-05-21 14 views
8

Ho una domanda su Linq/Lambda e il seguente problema:C# dizionari intersecano

Ho due dizionari, primaria e secondaria ... Questi due dizionari sono definite come chiave = stringa, un valore = int. Devo ridurre il dizionario principale se i KEYS si intersecano con il dizionario secondario.

cioè:

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] 

Il mio tentativo:

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

Questo, ovviamente, non funziona perché il primaryDict.Keys.Intersect restituisce un elenco di chiavi ... Come potrei ristabilire un nuovo dizionario o abbinare il dizionario principale? Qualsiasi aiuto sarebbe apprezzato.

risposta

17

Si potrebbe fare in questo modo:

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

o, in alternativa:

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

quest'ultimo forse è leggermente più efficiente perché evita la creazione di una collezione e getta (quello generato dal metodo Intersezione) e non richiede un secondo accesso-by-chiave a primaryDict.

EDIT (come da commento):

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

penso che l'ultima versione è molto meglio, come non credo che trattare il dizionario come un IEnumerable farà leva il Dizionario, e si svolgerà a O (n) tempo. –

+0

Che ha funzionato benissimo per quello che sto facendo ... Ho usato la seconda soluzione e tutto funziona come previsto. Fai rock Dave! –

+0

Come seguito ... è possibile sommare i valori in questa stessa espressione? –

2

testato:

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

È comunque possibile utilizzare primaryDict all'interno della vostra dichiarazione Linq dal momento che si sta creando un nuovo dizionario , che solo viene assegnato alla variabile una volta che è creato:

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