Załóżmy, że mam dwa słowniki Pythona - dictA
i dictB
. Muszę się dowiedzieć, czy są jakieś klucze, które są w środku, dictB
ale ich nie ma dictA
. Jak najszybciej można to zrobić?
Czy powinienem przekonwertować klucze słownika na zestaw, a następnie przejść?
Chcesz poznać swoje myśli ...
Dziękuję za odpowiedzi.
Przepraszam za niepoprawne sformułowanie mojego pytania. Mój scenariusz jest taki - mam, dictA
który może być taki sam, jak dictB
lub może brakować niektórych kluczy w porównaniu do dictB
lub wartość niektórych kluczy może być inna, co musi być ustawione dictA
na wartość klucza.
Problem polega na tym, że słownik nie ma standardu i może mieć wartości, które można dyktować.
Mówić
dictA={'key1':a, 'key2':b, 'key3':{'key11':cc, 'key12':dd}, 'key4':{'key111':{....}}}
dictB={'key1':a, 'key2:':newb, 'key3':{'key11':cc, 'key12':newdd, 'key13':ee}.......
Tak więc wartość „klucz2” musi zostać zresetowana do nowej wartości, a „klucz13” musi zostać dodana wewnątrz dykta. Wartość klucza nie ma ustalonego formatu. Może to być prosta wartość lub dyktando lub dyktando.
źródło
def update(self, new_dict): self.__init__(new_dict, self.current_dict)
lub coś podobnego, żebyś mógł zrobić kroczące porównanieDictDiffer
klasa jest klasą bezstanową i może być funkcją. Wartościchanged
iunchanged
można obliczyć w tej samej pętli. Te dwie funkcje mogą zwrócićlist
zamiast a,set
co jest z pewnością tańsze. Aby uzyskać szczegółowe porównanie, możesz przyjrzeć się strukturze testów jednostkowych: docs.python.org/2/library/unittest.html , po prostu postępuj zgodnie zassertDictEqual
metodą w kodzie źródłowym.set(dictb)
jest prawdopodobnie lepszy niżset(dictb.keys())
.Jeśli chcesz, aby różnica była rekurencyjna, napisałem pakiet dla Pythona: https://github.com/seperman/deepdiff
Instalacja
Zainstaluj z PyPi:
Przykładowe użycie
Importowanie
Ten sam obiekt zwraca pusty
Typ elementu się zmienił
Wartość pozycji uległa zmianie
Dodano i / lub usunięto element
Różnica strun
Różnica strun 2
Zmiana typu
Lista różnic
Różnica w liście 2:
Wypisz różnicę ignorując kolejność lub duplikaty: (z tymi samymi słownikami co powyżej)
Lista zawierająca słownik:
Zestawy:
Nazwane krotki:
Obiekty niestandardowe:
Dodano atrybut obiektu:
źródło
ignore_order=True
. Można znaleźć w dokumentacji na deepdiff.readthedocs.io/en/latest/diff.htmlnie jestem pewien, czy jest to „szybkie”, czy nie, ale normalnie można to zrobić
źródło
dicta
adictb
ponieważ chce wiedzieć, których kluczydictb
nie madicta
.for key in dicta.keys():
=>for key in dicta:
Jak napisał Alex Martelli, jeśli chcesz po prostu sprawdzić, czy któryś klawisz w B nie znajduje się w A,
any(True for k in dictB if k not in dictA)
będzie dobrym rozwiązaniem.Aby znaleźć brakujące klucze:
Więc te dwa rozwiązania mają prawie taką samą prędkość.
źródło
any(k not in dictA for k in dictB)
Jeśli naprawdę masz na myśli dokładnie to, co mówisz (że musisz tylko dowiedzieć się, JEŻELI „są jakieś klucze” w B, a nie w A, a nie KTÓRYCH mogą to być, jeśli w ogóle), najszybszym sposobem powinno być:
Jeśli naprawdę chcesz dowiedzieć się, które KLUCZE, jeśli w ogóle, znajdują się w B, a nie w A, a nie tylko „JEŚLI” są takie klucze, to istniejące odpowiedzi są całkiem odpowiednie (ale sugeruję większą precyzję w przyszłych pytaniach, jeśli tak rzeczywiście co masz na myśli ;-).
źródło
Zastosowanie
set()
:źródło
set(d)
już zwraca tylko klucze, więc możesz to zrobićset(da).intersection(db)
Najlepsza odpowiedź autorstwa hughdbrown sugeruje użycie różnicy zestawów, co jest zdecydowanie najlepszym podejściem:
Problem z tym kodem polega na tym, że buduje dwie listy tylko po to, aby utworzyć dwa zestawy, więc marnuje 4N czasu i 2N miejsca. Jest to też trochę bardziej skomplikowane, niż powinno.
Zwykle nie jest to wielka sprawa, ale jeśli tak jest:
collections.abc.Mapping
ma element,KeysView
który działa jak aSet
.Python 2
W Pythonie 2
keys()
zwraca listę kluczy, a nie plikKeysView
. Więc musisz zapytaćviewkeys()
bezpośrednio.W przypadku kodu z podwójną wersją 2.7 / 3.x, miejmy nadzieję, używasz
six
czegoś podobnego, więc możesz użyćsix.viewkeys(dictb)
:W 2.4-2.6 nie ma
KeysView
. Ale możesz przynajmniej obniżyć koszt z 4N do N, budując swój lewy zestaw bezpośrednio z iteratora, zamiast najpierw budować listę:Przedmiotów
Więc naprawdę nie musisz porównywać kluczy, ale przedmioty. A
ItemsView
jest tylkoSet
wtedy, gdy wartości są hashowane, jak ciągi. Jeśli tak, to proste:Różnica rekurencyjna
Chociaż pytanie nie dotyczy bezpośrednio rekurencyjnej różnicy, niektóre z przykładowych wartości są dyktami i wydaje się, że oczekiwany wynik różni je rekurencyjnie. Istnieje już wiele odpowiedzi pokazujących, jak to zrobić.
źródło
Jest jeszcze jedno pytanie w stackoverflow dotyczące tego argumentu i muszę przyznać, że jest wyjaśnione proste rozwiązanie: biblioteka datadiff w Pythonie pomaga wydrukować różnicę między dwoma słownikami.
źródło
Oto sposób, który zadziała, zezwala na klucze, które oceniają
False
i nadal używają wyrażenia generatora, aby wypadać wcześnie, jeśli to możliwe. Nie jest jednak wyjątkowo ładny.EDYTOWAĆ:
THC4k opublikował odpowiedź na mój komentarz dotyczący innej odpowiedzi. Oto lepszy, ładniejszy sposób wykonania powyższego:
Nie jestem pewien, jak to nigdy nie przyszło mi do głowy ...
źródło
any(k for k in dictB if k not in dictA)
co nie jest tym samym (dla kluczy falsey). Sprawdź historię zmian / znaczniki czasu.To jest stare pytanie i wymaga trochę mniej niż to, czego potrzebowałem, więc ta odpowiedź w rzeczywistości rozwiązuje więcej niż to pytanie. Odpowiedzi na to pytanie pomogły mi rozwiązać następujące kwestie:
Wszystko to w połączeniu z JSON zapewnia dość potężną obsługę magazynu konfiguracji.
Rozwiązanie ( również na githubie ):
źródło
co ze standardem (porównaj FULL Object)
PyDev-> nowy moduł PyDev-> Moduł: unittest
źródło
Jeśli na Pythonie ≥ 2,7:
źródło
Oto rozwiązanie do głębokiego porównania 2 kluczy słowników:
źródło
oto rozwiązanie, które może porównać więcej niż dwa dykty:
przykład użycia:
źródło
Mój przepis na symetryczną różnicę między dwoma słownikami:
A wynik to:
źródło
Jak wspomniano w innych odpowiedziach, unittest generuje niezłe dane wyjściowe do porównywania dykt, ale w tym przykładzie nie chcemy najpierw tworzyć całego testu.
Po skrobaniu najmniejszego źródła wygląda na to, że możesz uzyskać uczciwe rozwiązanie za pomocą tego:
więc
Prowadzi do:
Gdzie:
Podobnie jak w unittest, jedynym zastrzeżeniem jest to, że końcowe odwzorowanie można uznać za różnicę, ze względu na końcowy przecinek / nawias.
źródło
@Maxx ma doskonałą odpowiedź, skorzystaj z
unittest
narzędzi dostarczonych przez Pythona:Następnie w dowolnym miejscu kodu możesz zadzwonić:
Wynikowy wynik wygląda jak wyjście z
diff
, ładnie wypisując słowniki z+
lub-
poprzedzając każdą inną linię.źródło
Nie jestem pewien, czy to nadal jest istotne, ale natknąłem się na ten problem, w mojej sytuacji wystarczyło zwrócić słownik zmian dla wszystkich zagnieżdżonych słowników itp. Itp. Nie mogłem znaleźć dobrego rozwiązania, ale ostatecznie napisałem prostą funkcję zrobić to . Mam nadzieję że to pomoże,
źródło
Jeśli chcesz mieć wbudowane rozwiązanie do pełnego porównania z dowolnymi strukturami dyktowania, odpowiedź @ Maxx jest dobrym początkiem.
źródło
Na podstawie odpowiedzi ghostdog74,
wypisze inną wartość dicta
źródło
Spróbuj tego, aby znaleźć przecięcie, klucze, które są w obu słownikach, jeśli chcesz, aby klucze nie znalazły się w drugim słowniku, po prostu użyj nie w ...
źródło