2013-08-27 21 views
5

Więc mam listę słowników tak:Posortuj listę słowników podczas konsolidowania duplikatów w Pythonie?

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... 
     } ] 

Oczywiście, nie jest to dokładne dane. Ale (być może) z mojego przykładu tutaj możesz złapać mój problem. Mam wiele rekordów o tej samej nazwie "Organizacja", ale żadna z nich nie ma pełnej informacji o tej płycie.

Czy istnieje wydajny metoda poszukiwania na liście, sortowanie listy na podstawie słownika pierwszego wpisu, a na końcu scalania danych z duplikatów stworzyć unikalny wpis? (Należy pamiętać, te słowniki są dość duże)

Odpowiedz

3

Można skorzystać z 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) 

drukuje:

{'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:

Oto co można zrobić, aby grupy elementy w jeden dyktat:

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']) 

następnie w result będziesz mieć:

{'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

Przetestowałem Twój kod i nie jest to dokładnie to, czego potrzebuję. Dzięki za pokazanie mi tego rodzaju, to było niesamowite. Szukam sposobu na połączenie wszystkich słowników o tej samej nazwie organizacji do jednego słownika na tej samej liście. –

+0

Oczywiście, możesz z tego zrobić jeden słownik. Po prostu użyj tej zmiennej 'group'. – alecxe

+0

@ Jacob-IT, zaktualizowałem odpowiedź, sprawdź. – alecxe

2

Czy istnieje skuteczny sposób poszukiwania na liście, sortowanie listy na podstawie słownika pierwszego wpisu, a na końcu scalania danych z duplikatów do tworzenia unikalny wpis?

Tak, ale istnieje jeszcze bardziej wydajna metoda bez wyszukiwania i sortowania. Wystarczy zbudować słownika jak iść:

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

Teraz masz co liniową podaniem danych, robi odnośnika stałą czasową dla każdej z nich. Jest więc lepsze niż jakiekolwiek posortowane rozwiązanie przez współczynnik O (log N). Jest to również jedno przejście zamiast wielu przejść i prawdopodobnie będzie miało niższy stały narzut.


Nie jest jasne, co dokładnie chcesz zrobić, aby scalić wpisy, i nie ma sposobu, każdy może napisać kod nie wiedząc, co rządzi chcesz użyć. Ale oto prosty przykład:

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

Innymi słowy, dla każdego elementu w d2, jeśli d1 ma już wartość truthy (jak niepustym ciągiem), zostawić go w spokoju; w przeciwnym razie dodaj.

+0

Czy masz jakieś sugestie dotyczące funkcji "scalania"? –

+0

To jest łatwa część; Zakładałem, że już wiesz, jak to zrobić.Ale będę edytować odpowiedź, aby pokazać przykład: – abarnert

+0

Jestem nowy w Python..sorry, jeśli wydaje mi się, nie. –