Mam listę dykt i chciałbym usunąć dykty z identycznymi parami klucza i wartości.
W przypadku tej listy: [{'a': 123}, {'b': 123}, {'a': 123}]
Chciałbym to zwrócić: [{'a': 123}, {'b': 123}]
Inny przykład:
W przypadku tej listy: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}]
Chciałbym to zwrócić: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
python
list
dictionary
Brenden
źródło
źródło
set()
Odpowiedzi:
Spróbuj tego:
Strategia polega na przekonwertowaniu listy słowników na listę krotek, w której krotki zawierają pozycje ze słownika. Ponieważ krotki mogą być haszowane, możesz usunąć duplikaty za pomocą
set
(używając zestawu pojmowania tutaj, starsza alternatywa dla Pythona będzieset(tuple(d.items()) for d in l)
), a następnie ponownie utwórz słowniki z krotek za pomocądict
.gdzie:
l
to oryginalna listad
jest jednym ze słowników na liściet
jest jedną z krotek utworzonych ze słownikaEdycja: Jeśli chcesz zachować kolejność, powyższa linijka nie zadziała, ponieważ
set
tego nie zrobi. Jednak za pomocą kilku wierszy kodu możesz również to zrobić:Przykładowe dane wyjściowe:
Uwaga: jak wskazał @alexis, może się zdarzyć, że dwa słowniki z tymi samymi kluczami i wartościami nie utworzą tej samej krotki. Może się to zdarzyć, jeśli przejdą przez inną historię dodawania / usuwania kluczy. Jeśli tak jest w przypadku Twojego problemu, rozważ sortowanie
d.items()
zgodnie z sugestią.źródło
d.items()
nie ma gwarancji zwrotu elementów w określonej kolejności. Powinieneś zrobić,tuple(sorted(d.items()))
aby upewnić się, że nie otrzymasz różnych krotek dla tych samych par klucz-wartość.json
modułu, tak jak jaKolejna jedna linijka oparta na zrozumieniu list:
Tutaj, ponieważ możemy użyć
dict
porównania, zachowujemy tylko te elementy, których nie ma w pozostałej części początkowej listy (to pojęcie jest dostępne tylko przez indeksn
, stąd użycieenumerate
).źródło
if i not in d[n + 1:]
iteruje po całej liście poleceń (od,n
ale to tylko zmniejsza o połowę całkowitą liczbę operacji) i robisz to sprawdzanie każdego elementu w słowniku, więc ten kod ma złożoność czasową O (n ^ 2)Inne odpowiedzi nie zadziałają, jeśli pracujesz na zagnieżdżonych słownikach, takich jak zdeserializowane obiekty JSON. W tym przypadku możesz użyć:
źródło
Jeśli użycie pakietu innej firmy byłoby w porządku, możesz użyć
iteration_utilities.unique_everseen
:Zachowuje kolejność oryginalnej listy i ut może również obsługiwać elementy, których nie można zhasować, takie jak słowniki, wycofując się na wolniejszym algorytmie (
O(n*m)
gdzie zamiast elementów oryginalnej listyn
znajdują się elementy oryginalnej listy im
unikalne elementy na oryginalnej liścieO(n)
). W przypadku, gdy zarówno klucze, jak i wartości są hashowalne, możesz użyćkey
argumentu tej funkcji do utworzenia pozycji hashable dla „testu unikalności” (tak, aby działałO(n)
).W przypadku słownika (który porównuje niezależnie od kolejności) musisz odwzorować go na inną strukturę danych, która porównuje w ten sposób, na przykład
frozenset
:Zwróć uwagę, że nie powinieneś używać prostego
tuple
podejścia (bez sortowania), ponieważ równe słowniki niekoniecznie mają tę samą kolejność (nawet w Pythonie 3.7, gdzie kolejność wstawiania - a nie kolejność bezwzględna - jest gwarantowana):A nawet sortowanie krotki może nie działać, jeśli klucze nie są sortowalne:
Reper
Pomyślałem, że warto zobaczyć, jak wypada porównanie tych podejść, więc zrobiłem mały test porównawczy. Wykresy porównawcze przedstawiają czas w funkcji rozmiaru listy na podstawie listy nie zawierającej duplikatów (która została wybrana arbitralnie, czas wykonania nie zmienia się znacząco, jeśli dodam kilka lub wiele duplikatów). Jest to wykres log-log, więc obejmuje cały zakres.
Absolutne czasy:
Czasy w stosunku do najszybszego podejścia:
Drugie podejście od czwórki jest tutaj najszybsze.
unique_everseen
Podejście zkey
funkcji znajduje się na drugim miejscu, jednak jest to najszybszy podejście, że przetwory zamówić. Inne podejścia z jcollado i the fourye są prawie tak samo szybkie. Podejścieunique_everseen
bez klucza i rozwiązania Emmanuel i Scorpil są bardzo powolne w przypadku dłuższych list iO(n*n)
zamiast tego zachowują się znacznie gorzejO(n)
. Podejście stpk zjson
nie jest,O(n*n)
ale jest znacznie wolniejsze niż podobneO(n)
podejścia.Kod do odtworzenia wzorców:
Aby uzyskać kompletność, oto czas dla listy zawierającej tylko duplikaty:
Czasy nie zmieniają się znacząco, z wyjątkiem
unique_everseen
brakukey
funkcji, co w tym przypadku jest najszybszym rozwiązaniem. Jest to jednak najlepszy przypadek (a więc niereprezentatywny) dla tej funkcji z wartościami, których nie można zhasować, ponieważ jej czas wykonywania zależy od liczby unikatowych wartości na liście:O(n*m)
w tym przypadku jest to tylko 1, a zatem działaO(n)
.Zastrzeżenie: jestem autorem
iteration_utilities
.źródło
Czasami pętle w starym stylu są nadal przydatne. Ten kod jest trochę dłuższy niż jcollado, ale bardzo łatwy do odczytania:
źródło
0
Wrange(0, len(a))
nie jest konieczne.Jeśli chcesz zachować Zakon, możesz to zrobić
Jeśli kolejność nie ma znaczenia, możesz to zrobić
źródło
dict_values
dane wyjściowe zamiast listy. Musisz ponownie rzucić całość na listę.list(frozen.....)
Jeśli używasz Pand w swoim przepływie pracy, jedną z opcji jest przesłanie listy słowników bezpośrednio do
pd.DataFrame
konstruktora. Następnie użyj metoddrop_duplicates
ito_dict
, aby uzyskać wymagany wynik.źródło
Nie jest to uniwersalna odpowiedź , ale jeśli zdarzy się, że twoja lista jest posortowana według jakiegoś klucza, na przykład:
to rozwiązanie jest tak proste, jak:
Wynik:
Działa z zagnieżdżonymi słownikami i (oczywiście) zachowuje porządek.
źródło
Możesz użyć zestawu, ale musisz zmienić dykty w typ haszujący.
Wyjątkowy teraz równa się
Aby odzyskać dyktowanie:
źródło
d.iteritems()
nie jest gwarantowana - więc możesz otrzymać „duplikaty” w formacieunique
.Oto szybkie, jednowierszowe rozwiązanie z podwójnie zagnieżdżonym zrozumieniem list (w oparciu o rozwiązanie @Emmanuel).
To używa pojedynczego klucza (na przykład
a
) w każdym dyktacie jako klucza podstawowego, zamiast sprawdzać, czy cały dykt jest zgodnyNie o to prosił OP, ale to właśnie doprowadziło mnie do tego wątku, więc pomyślałem, że opublikuję rozwiązanie, z którym skończyłem
źródło
Nie tak krótkie, ale łatwe do odczytania:
Teraz lista
list_of_data_uniq
będzie miała unikalne dykty.źródło