2013-07-24 16 views
7

Sto cercando di scrivere la comprensione che comporranno due dizionari nel seguente modo:Python: la comprensione di comporre due dizionari

d1 = {1:'a',2:'b',3:'c'} 
d2 = {'a':'A','b':'B','c':'C'} 
result = {1:'A',2:'B',3:'C'} 

Cioè, il dizionario risultante è formato dalle chiavi del primo e i valori del secondo per ogni coppia in cui il valore del primo è uguale alla chiave del secondo.

Questo è quello che ho finora:

{ k1:v2 for (k1,v1) in d1 for (k2,v2) in d2 if v1 == k2 } 

ma non funziona. Sono nuovo di Python quindi non sono sicuro se questo ha davvero senso. A proposito, sto usando python 3.3.2.

Grazie in anticipo.

+0

Grazie a tutti, vorrei poterne accettare più di uno. – Roma149

risposta

9

Un modo per farlo è:

result = {k: d2.get(v) for k, v in d1.items()} 

Quale comportamento volevi per le chiavi che hanno un valore che non è in d2?

+0

+1 per non andare in crash quando 'd2' non ha una chiave per qualche valore in' d1'. –

+0

Funziona come un fascino, grazie mille. Ho un set fisso di input, che so avere quel formato, quindi va bene se lasciamo quel comportamento non specificato. – Roma149

+1

Giusto per essere esplicito - il precedente fornirà a qualsiasi chiave non abbinata il valore 'None'. Per omettere le chiavi non corrispondenti, dovresti usare '{k: d2 [v] per k, v in d1.items() se v in d2}' –

6

Basta ciclo tra gli elementi di d1 e poi per ogni elemento che si desidera mettere nel risultato non utilizzare il valore da d1 ma invece cercare il nuovo valore all'interno d2 utilizzando d1 's valore come la chiave:

>>> d1 = {1: 'a', 2: 'b', 3: 'c'} 
>>> d2 = {'a': 'A', 'b': 'B', 'c': 'C'} 
>>> d = {k: d2[v] for (k, v) in d1.items()} 
>>> d 
{1: 'A', 2: 'B', 3: 'C'} 
2

in questo modo funziona anche se non tutti i valori sono d1 chiavi valide per d2:

{k1:d2[d1[k1]] for k1 in d1 if d1[k1] in d2} 
2
This is what I've got so far: 

    { k1:v2 for (k1,v1) in d1 for (k2,v2) in d2 if v1 == k2 } 

Due cose che si dovrebbe notare:

1) Quando si utilizza un ciclo for-in direttamente su una dict:

for (k1, v1) in some_dict: 

loop pitone le chiavi del dict, vale a dire che, per-in loop è equivalente a:

for (k1, v1) in some_dict.keys() 

Ma si sta dicendo python che ci sarà una due tupla restituita ogni volta attraverso il ciclo, (k1, v1), e Python restituisce solo una chiave di volta in volta attraverso il ciclo. Quindi questo è un errore. È possibile correggere che scrivendo:

for (k1, v1) in some_dict.items() 

La funzione articoli() restituisce una tupla a due: (chiave, valore) di volta in volta attraverso il ciclo.

2) Supponiamo di avere questi dati:

data = [ 
    [1, 2, 3], 
    ['a', 'b', 'c'] 
] 

Per un ciclo su ciascuno dei sei valori, ci si sente naturale per scrivere:

results = [x for x in inner_array for inner_array in data] 

Ma che produce l'errore:

Traceback (most recent call last): 
    File "1.py", line 5, in <module> 
    results = [x for x in inner_array for inner_array in data] 
NameError: name 'inner_array' is not defined 

Per farlo funzionare, i loop devono essere scritti "all'indietro":

results = [x for inner_array in data for x in inner_array] 
print results 

--output:-- 
[1, 2, 3, 'a', 'b', 'c'] 

Penso che il modo più semplice per ricordare che è: i loop sono nello stesso ordine come se li hai scritto senza una lista di comprensione:

results = [] 

for inner_array in data: 
    for x in inner_array: 
     results.append(x) 

Personalmente, mi piacerebbe vedere che ha cambiato in python, in modo che all'interno di una lista/dict/set di comprensione tu lavori da "dentro e fuori", come hai scritto tu. In ogni caso, questo è il tuo codice con le modifiche:

d1 = {1:'a',2:'b',3:'c'} 
d2 = {'a':'A','b':'B','c':'C'} 

results = { 
     k1: v2 
     for (k2,v2) in d2.items() 
     for (k1,v1) in d1.items() if v1 == k2 
} 

print results 

--output:-- 
{1: 'A', 2: 'B', 3: 'C'} 
+0

@ Roma149, Potrebbe essere utile controllare la mia spiegazione di ciò che hai fatto sbagliato quando scrivi la tua comprensione del ditt. – 7stud

+0

Wow, spiegazione eccezionale, lo apprezzo davvero. Sembra che la mia versione abbia avuto un qualche senso dopotutto :) – Roma149

+0

@ Roma149, Yep. L'hai quasi avuto. Buon per un principiante – 7stud

Problemi correlati