2013-08-27 10 views
5

quindi ho una lista di dizionari in questo modo:Ordina un elenco di dizionari durante il consolidamento dei duplicati in Python?

data = [ { 
      'Organization' : '123 Solar', 
      'Phone' : '444-444-4444', 
      'Email' : '', 
      'website' : 'www.123solar.com' 
     }, { 
      'Organization' : '123 Solar', 
      'Phone' : '', 
      'Email' : '[email protected]', 
      'Website' : 'www.123solar.com' 
     }, { 
      etc... 
     } ] 

Naturalmente, questo non è i dati esatti. Ma (forse) dal mio esempio qui puoi cogliere il mio problema. Ho molti record con lo stesso nome "Organizzazione", ma nessuno di loro ha le informazioni complete per quel record.

Esiste un efficiente metodo di per la ricerca sulla lista, l'ordinamento l'elenco in base alla prima entrata del dizionario, e, infine, la fusione dei dati provenienti da duplicati per creare un unico ingresso ? (Tenete a mente questi dizionari sono piuttosto grandi)

risposta

3

È possibile fare uso di itertools.groupby:

from itertools import groupby 
from operator import itemgetter 
from pprint import pprint 

data = [ { 
      'Organization' : '123 Solar', 
      'Phone' : '444-444-4444', 
      'Email' : '', 
      'website' : 'www.123solar.com' 
     }, { 
      'Organization' : '123 Solar', 
      'Phone' : '', 
      'Email' : '[email protected]', 
      'Website' : 'www.123solar.com' 
     }, 
     { 
      'Organization' : '234 test', 
      'Phone' : '111', 
      'Email' : '[email protected]', 
      'Website' : 'b.123solar.com' 
     }, 
     { 
      'Organization' : '234 test', 
      'Phone' : '222', 
      'Email' : '[email protected]', 
      'Website' : 'bd.123solar.com' 
     }] 


data = sorted(data, key=itemgetter('Organization')) 
result = {} 
for key, group in groupby(data, key=itemgetter('Organization')): 
    result[key] = [item for item in group] 

pprint(result) 

stampe:

{'123 Solar': [{'Email': '', 
       'Organization': '123 Solar', 
       'Phone': '444-444-4444', 
       'website': 'www.123solar.com'}, 
       {'Email': '[email protected]', 
       'Organization': '123 Solar', 
       'Phone': '', 
       'Website': 'www.123solar.com'}], 
'234 test': [{'Email': '[email protected]', 
       'Organization': '234 test', 
       'Phone': '111', 
       'Website': 'b.123solar.com'}, 
       {'Email': '[email protected]', 
       'Organization': '234 test', 
       'Phone': '222', 
       'Website': 'bd.123solar.com'}]} 

UPD:

Ecco cosa si può fare per gruppo articoli in singole dict:

for key, group in groupby(data, key=itemgetter('Organization')): 
    result[key] = {'Phone': [], 
        'Email': [], 
        'Website': []} 
    for item in group: 
     result[key]['Phone'].append(item['Phone']) 
     result[key]['Email'].append(item['Email']) 
     result[key]['Website'].append(item['Website']) 

poi, in result avrai:

{'123 Solar': {'Email': ['', '[email protected]'], 
       'Phone': ['444-444-4444', ''], 
       'Website': ['www.123solar.com', 'www.123solar.com']}, 
'234 test': {'Email': ['[email protected]', '[email protected]'], 
       'Phone': ['111', '222'], 
       'Website': ['b.123solar.com', 'bd.123solar.com']}} 
+0

Ho testato il codice e non è esattamente quello di cui ho bisogno. Grazie per avermi mostrato il tipo, è stato fantastico. Sto cercando un modo per combinare tutti i dizionari con lo stesso nome di organizzazione in un unico dizionario nella stessa lista. –

+0

Certo, puoi creare un dizionario da questo. Basta usare quella variabile 'gruppo'. – alecxe

+0

@ Jacob-IT, ho aggiornato la risposta, per favore controlla. – alecxe

2

Esiste un metodo efficiente per la ricerca sulla lista, l'ordinamento l'elenco in base alla prima entrata del dizionario, e, infine, la fusione dei dati provenienti da duplicati per creare una voce unica?

Sì, ma c'è un metodo ancora più efficiente senza ricerca e ordinamento. Basta costruire un dizionario come si va avanti:

datadict = {} 
for thingy in data: 
    organization = thingy['Organization'] 
    datadict[organization] = merge(thingy, datadict.get(organization, {})) 

Ora hai facendo un passaggio lineare sui dati, facendo una ricerca costante di tempo per ciascuno di essi. Quindi, è migliore di qualsiasi soluzione ordinata per un fattore di O (log N). È anche un passaggio invece di più passaggi, e probabilmente avrà anche un overhead costante più basso.


Non è chiaro esattamente ciò che si vuole fare per unire le voci, e non c'è modo chiunque può scrivere il codice senza sapere quali regole che si desidera utilizzare. Ma qui è un semplice esempio:

def merge(d1, d2): 
    for key, value in d2.items(): 
     if not d1.get(key): 
      d1[key] = value 
    return d1 

In altre parole, per ogni elemento d2, se d1 ha già un valore truthy (come una stringa non vuota), lascia stare; altrimenti, aggiungilo.

+0

Hai qualche suggerimento per una funzione 'unire'? –

+0

Questa è la parte facile; Supponevo che tu sapessi già come farlo.Ma modifico la risposta per mostrare un esempio: – abarnert

+0

Sono nuovo di Python .. mi dispiace se sembro dunce. –