2015-06-10 5 views
6

Sono relativamente nuovo a Python 2.7, e non riesco a capire il seguente, nonostante la ricerca ampiamente su StackOverflow:Unisci valori della stessa chiave, nella lista dei dicts

Ho un list di dict s I wan't combinare, quando la chiave è la stessa, e aggiungere valori specifici (nell'esempio 'price').

ingresso:

[{'id1': 'a', 'price': '2', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}, {'id1': 'a', 'price': '2', 'color': 'green'}] 

atteso:

[{'id1': 'a', 'price': '4', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}] 

risposta

4

stessa idea la tua domanda prima della modifica.

>>> data = [{'id1': 'a', 'price': '2', 'color': 'green'}, 
...   {'id1': 'b', 'price': '5', 'color': 'red'}, 
...   {'id1': 'a', 'price': '2', 'color': 'green'}] 

costruire un dizionario temporanea e si accumulano i valori in esso

>>> temp = {} 
>>> for d in data: 
...  if d['id1'] not in temp: 
...   temp[d['id1']] = {} 
...  temp_d = temp[d['id1']] 
...  temp_d['price'] = temp_d.get('price', 0) + int(d['price']) 
...  temp_d.setdefault('colors', set()).add(d['color']) 
... 
>>> temp 
{'a': {'colors': {'green'}, 'price': 4}, 'b': {'colors': {'red'}, 'price': 5}} 

Quindi, utilizzando la lista di comprensione e di comprensione dizionario, ricostruire l'elenco dei dizionari.

>>> [{'id1': k, 'price': v['price'], 'colors': v['colors']} for k, v in temp.items()] 
[{'id1': 'a', 'colors': {'green'}, 'price': 4}, {'id1': 'b', 'colors': {'red'}, 'price': 5}] 

>>> data = [{'id1': 'a', 'price': '2'}, {'id1': 'b', 'price': '5'}, 
...   {'id1': 'a', 'price': '2'}] 

creare un dizionario temporanea in cui siamo in grado di accummulate la somma dei prezzi contro la loro ID,

>>> temp = {} 
>>> for d in data: 
...  temp[d['id1']] = temp.get(d['id1'], 0) + int(d['price']) 
... 
>>> temp 
{'a': 4, 'b': 5} 

Qui si cerca di ottenere il valore di d['id1'] da temp e se non viene trovato, 0 verrà restituito. Quindi aggiungiamo il price dal dizionario corrente e memorizziamo il risultato nello temp rispetto all'id1 corrente.

Poi ricostruire l'elenco dei dizionari, con list comprehension e dizionario di comprensione, come questo

>>> [{'id1': k, 'price': temp[k]} for k in temp] 
[{'price': 4, 'id1': 'a'}, {'price': 5, 'id1': 'b'}] 
+0

Very nice. L'unico problema è che il primo dict in realtà ha un altro valore, colore, in una delle occorrenze {'id1': 'a', 'prezzo': '2', 'colore': 'rosso'} Come posso mantenere questo in l'ultimo atto? – DauleDK

+0

@DauleDK Il colore sarà lo stesso per il dato id1 in tutti i dizionari? Ad esempio, se 'id1' è' a' e il colore sarà sempre 'green'? – thefourtheye

+0

Non sempre, forse è possibile concatenare i valori? – DauleDK

0

Questo non è così bello come @thefourtheye, ma sembra funzionare per me:

di = [{'id1': 'a', 'price': '2', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}, {'id1': 'a', 'price': '2', 'color': 'green'}] 

# Make a dict to hold new values! 
newvals = {} 

for d in di: 
    for key, value in d.iteritems(): 
     if value.isdigit(): 
      if value in newvals: 
       newvals[value] += int(value) 
      else: 
       newvals[value] = int(value) 
     else: 
      if value not in newvals: 
       newvals[value] = value 

for d in di: 
    for nkey, nvalue in d.iteritems(): 
     d[nkey] = newvals[nvalue] 

# Make a unique list of dicts 
print {v['id1']:v for v in di}.values() 

>>>[{'color': 'green', 'price': 4, 'id1': 'a'}, {'color': 'red', 'price': 5, 'id1': 'b'}]