Powiedzmy, że mam listę słowników:
[
{'id': 1, 'name': 'john', 'age': 34},
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
i muszę uzyskać listę unikalnych słowników (usuwanie duplikatów):
[
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
Czy ktoś może mi pomóc w najbardziej efektywnym sposobie osiągnięcia tego w Pythonie?
python
dictionary
Limaaf
źródło
źródło
set(frozenset(i.items()) for i in list)
Odpowiedzi:
Zrób więc tymczasowy dykt, w którym klucz będzie
id
. To odfiltrowuje duplikaty. Plikvalues()
Z dict będzie listaW Pythonie 2.7
W Python3
W Pythonie 2.5 / 2.6
źródło
{str(v['flight'])+':'+str(v['lon'])+','+str(v['lat']): v for v in stream}.values()
To po prostu tworzy unikalny klucz oparty na twoich wartościach. Jak'MH370:-21.474370,86.325589'
{(v['flight'], v['lon'], v['lat']): v for v in stream}.values()
OrderedDict
zcollections
list(OrderedDict((v['id'], v) for v in L).values())
lub sortowanie listy wynikowej, czy działa lepiej dla ciebielist({str(i):i for i in L}.values())
Tutaj używamy str (i) do stworzenia unikalnego ciągu, który reprezentuje słownik, który jest używany do filtrowania duplikatów.Zwykłym sposobem znalezienia tylko wspólnych elementów w zestawie jest użycie
set
klasy Pythona . Po prostu dodaj wszystkie elementy do zestawu, a następnie przekonwertuj zestaw na alist
i bam, że duplikaty zniknęły.Problem polega oczywiście na tym, że a
set()
może zawierać tylko wpisy z funkcją hashowania, a adict
nie może zawierać hashable.Gdybym miał ten problem, moim rozwiązaniem byłoby przekonwertowanie każdego z nich
dict
na ciąg, który reprezentujedict
, a następnie dodanie wszystkich ciągów do a,set()
a następnie odczytanie wartości ciągu jako alist()
i konwersja z powrotem dodict
.Dobrą reprezentacją a
dict
w postaci ciągu jest format JSON. A Python ma wbudowany moduł dla JSON (nazywanyjson
oczywiście).Pozostały problem polega na tym, że elementy w a
dict
nie są uporządkowane, a gdy Python konwertujedict
ciąg na ciąg JSON, możesz otrzymać dwa ciągi JSON, które reprezentują równoważne słowniki, ale nie są identycznymi ciągami. Prostym rozwiązaniem jest przekazanie argumentusort_keys=True
podczas wywołaniajson.dumps()
.EDYCJA: To rozwiązanie zakładało, że dana część
dict
może mieć inną część. Jeśli możemy założyć, że każdydict
o tej samej"id"
wartości będzie pasował do wszystkichdict
o tej samej"id"
wartości, to jest to przesada; Rozwiązanie @ gnibbler byłoby szybsze i łatwiejsze.EDYCJA: Teraz jest komentarz André Limy, który wyraźnie mówi, że jeśli identyfikator jest duplikatem, można bezpiecznie założyć, że całość
dict
jest duplikatem. Więc ta odpowiedź jest przesada i polecam odpowiedź @ gnibbler.źródło
W przypadku, gdy słowniki są jednoznacznie identyfikowane przez wszystkie pozycje (identyfikator nie jest dostępny), możesz użyć odpowiedzi za pomocą JSON. Poniżej przedstawiono alternatywę, która nie używa formatu JSON i będzie działać, o ile wszystkie wartości słownika są niezmienne
źródło
Możesz użyć biblioteki numpy (działa tylko dla Python2.x):
Aby zadziałało z Pythonem 3.x (i ostatnimi wersjami numpy), musisz przekonwertować tablicę dykt na tablicę ciągów numpy, np.
źródło
TypeError: unorderable types: dict() > dict()
, robiąc to w Pythonie 3.5.Oto dość kompaktowe rozwiązanie, choć podejrzewam, że nie jest szczególnie wydajne (delikatnie mówiąc):
źródło
map()
wywołanielist()
w Pythonie 3, aby otrzymać listę z powrotem, w przeciwnym razie jest tomap
obiekt.Ponieważ
id
jest wystarczający do wykrywania duplikatów, aid
jest hashable: przepuść je przez słownik, który maid
jako klucz. Wartością każdego klucza jest oryginalny słownik.W Pythonie 3
values()
nie zwraca listy; musisz zawinąć całą prawą stronę tego wyrażenialist()
, a treść wyrażenia możesz zapisać bardziej ekonomicznie jako dyktowanie:Zwróć uwagę, że wynik prawdopodobnie nie będzie w tej samej kolejności, co oryginał. Jeśli jest to wymagane, możesz użyć
Collections.OrderedDict
zamiastdict
.Na marginesie, sensowne może być po prostu przechowywanie danych w słowniku, w którym na początku jest używany
id
klucz as.źródło
wyjścia:
źródło
Rozszerzając odpowiedź Johna La Rooy'a ( Python - Lista unikalnych słowników ), czyniąc ją nieco bardziej elastyczną:
Funkcja dzwonienia:
źródło
Możemy zrobić
pandas
Uwaga nieco różni się od akceptowanej odpowiedzi.
drop_duplicates
sprawdzi wszystkie kolumny w pandach, jeśli wszystkie są takie same, wiersz zostanie usunięty.Na przykład :
Jeśli zmienimy drugie
dict
imię z jan na peterźródło
W Pythonie 3.6+ (co testowałem) wystarczy użyć:
Wyjaśnienie: mapujemy,
json.dumps
aby zakodować słowniki jako obiekty json, które są niezmienne.set
może być następnie użyty do stworzenia iterowalnych unikatowych niezmiennych. Na koniec konwertujemy z powrotem do naszej reprezentacji słownikowej za pomocąjson.loads
. Zwróć uwagę, że początkowo należy posortować według kluczy, aby uporządkować słowniki w unikalnej formie. Dotyczy to Pythona 3.6+, ponieważ słowniki są uporządkowane domyślnie.źródło
list
przed wykonaniemset
.Podsumowałem swoje ulubione do wypróbowania:
https://repl.it/@SmaMa/Python-List-of-unique-dictionaries
źródło
Szybkim i łatwym rozwiązaniem jest po prostu wygenerowanie nowej listy.
źródło
Nie wiem, czy chcesz, aby tylko identyfikatory twoich dykt na liście były unikalne, ale jeśli celem jest posiadanie zestawu dykt, w którym niepowtarzalność jest na wartościach wszystkich kluczy ... powinieneś użyć klucza krotek w ten sposób w twoim zrozumieniu:
Mam nadzieję, że pomoże to tobie lub innej osobie, która ma obawy ....
źródło
Odpowiedzi jest tutaj wiele, więc pozwól mi dodać kolejne:
źródło
Całkiem prosta opcja:
źródło
Cóż, wszystkie wymienione tutaj odpowiedzi są dobre, ale w niektórych odpowiedziach można napotkać błąd, jeśli elementy słownika mają zagnieżdżoną listę lub słownik, więc proponuję prostą odpowiedź
źródło
Oto implementacja z niewielkim narzutem pamięci, kosztem mniejszego rozmiaru niż reszta.
wynik:
źródło
index
atlen(values)
i liczenie wstecz, co oznacza, że zawsze możesz zmniejszyć wartość,index
czydel
nie. np.for index in reversed(range(len(values))):
Oto rozwiązanie, które znalazłem:
Zasadniczo sprawdzasz, czy identyfikator jest obecny na liście, jeśli tak, usuń słownik, jeśli nie, dołącz identyfikator do listy
źródło