Mam dwa słowniki, ale dla uproszczenia wezmę te dwa:
>>> x = dict(a=1, b=2)
>>> y = dict(a=2, b=2)
Teraz chcę porównać, czy każda key, value
para x
ma tę samą odpowiadającą wartość w y
. Więc napisałem to:
>>> for x_values, y_values in zip(x.iteritems(), y.iteritems()):
if x_values == y_values:
print 'Ok', x_values, y_values
else:
print 'Not', x_values, y_values
I działa, ponieważ a tuple
jest zwracane, a następnie porównywane pod kątem równości.
Moje pytania:
Czy to jest poprawne? Czy jest na to lepszy sposób? Lepiej nie w szybkości, mówię o elegancji kodu.
AKTUALIZACJA: Zapomniałem wspomnieć, że muszę sprawdzić, ile key, value
par jest równych.
python
dictionary
comparison
użytkownik225312
źródło
źródło
x == y
powinno być prawdziwe zgodnie z stackoverflow.com/a/5635309/186202Odpowiedzi:
Jeśli chcesz wiedzieć, ile wartości pasuje do obu słowników, powinieneś to powiedzieć :)
Może coś takiego:
źródło
list
kluczem.x = {[1,2]: 2}
zawiedzie. Pytanie jest już ważnedicts
.list
kluczami nie jest prawidłowym kodem Pythona - klucze dykta muszą być niezmienne. Dlatego nie porównujesz słowników. Jeśli spróbujesz użyć listy jako klucza słownika, Twój kod nie zostanie uruchomiony. Nie masz obiektów do porównania. To tak, jakby pisać,x = dict(23\;dfg&^*$^%$^$%^)
a następnie narzekać, że porównanie nie działa ze słownikiem. Oczywiście, że to nie zadziała. Z drugiej strony komentarz Tima dotyczy zmiennościvalues
, dlatego powiedziałem, że są to różne problemy.set
wymaga, aby wartości były haszowalne, adict
klucze muszą być haszowalne.set(x.keys())
zawsze będzie działać, ponieważ klucze muszą być haszowalne, aleset(x.values())
zawiodą na wartościach, które nie są haszowalne.To, co chcesz zrobić, to po prostu
x==y
To, co robisz, nie jest dobrym pomysłem, ponieważ elementy w słowniku nie powinny mieć żadnej kolejności. Możesz porównywać
[('a',1),('b',1)]
z[('b',1), ('a',1)]
(te same słowniki, inna kolejność).Zobacz na przykład:
Różnica to tylko jeden element, ale Twój algorytm zobaczy, że wszystkie elementy są różne
źródło
źródło
DataFrame
z założenia nie pozwalają na prawdziwe porównania (chyba że ma długość 1), ponieważ dziedzicząnumpy.ndarray
. -kredyt na stackoverflow.com/a/33307396/994076dic1 == dic2
Z dokumentacji Pythona :
Obowiązuje zarówno dla, jak
py2
i dlapy3
.źródło
OrderedDict != dict
Jestem nowy w Pythonie, ale skończyło się na zrobieniu czegoś podobnego do @mouad
Operator XOR (
^
) powinien wyeliminować wszystkie elementy dict, gdy są one takie same w obu dictach.źródło
{'a':{'b':1}}
dajeTypeError: unhashable type: 'dict'
)Ponieważ wydaje się, że nikt o tym nie wspomniał
deepdiff
, dodam go tutaj dla kompletności. Uważam, że bardzo wygodne jest uzyskiwanie różnych (zagnieżdżonych) obiektów w ogóle:Instalacja
Przykładowy kod
Wynik
Uwaga o ładnym wydrukowaniu wyniku do kontroli: powyższy kod działa, jeśli oba nagrania mają te same klucze atrybutów (z możliwie różnymi wartościami atrybutów jak w przykładzie). Jeśli jednak
"extra"
atrybut jest obecny, to jeden ze słowników,json.dumps()
kończy się niepowodzeniemRozwiązanie: użyj
diff.to_json()
ijson.loads()
/json.dumps()
do ładnego wydruku:Wynik:
Alternatywnie: użyj
pprint
, powoduje inne formatowanie:Wynik:
źródło
Po prostu użyj:
źródło
dict1 == dict2
cmp
wbudowane zostało usunięte (i powinno być traktowane jako usunięte wcześniej . Alternatywa, którą proponują:(a > b) - (a < b) == cmp(a, b)
dla funkcjonalnego odpowiednika (lub lepszego__eq__
i__hash__
)TypeError
:unorderable types: dict() < dict()
Odpowiedź @mouada jest dobra, jeśli założymy, że oba słowniki zawierają tylko proste wartości. Jeśli jednak masz słowniki zawierające słowniki, otrzymasz wyjątek, ponieważ słowniki nie podlegają haszowaniu.
Z czubka mojej głowy może działać coś takiego:
źródło
not isinstance(dict1, dict)
zamiasttype(dict1) is not dict
, będzie to działać na innych klasach opartych nadict. Also, instead of
(dict1 [klucz] == dict2 [klucz]), you can do
wszystkie (atleast_1d (dict1 [klucz] == dict2 [klucz])) `przynajmniej do obsługi tablic.for loop
gdy tylko stanieszdicts_are_equal
się fałszywy. Nie trzeba kontynuować.Jeszcze inną możliwością, aż do ostatniej nuty OP, jest porównanie skrótów (
SHA
lubMD
) nagrań zrzuconych jako JSON. Sposób budowania skrótów gwarantuje, że jeśli są one równe, łańcuchy źródłowe są również równe. Jest to bardzo szybkie i matematyczne.źródło
json.dumps(d, sort_keys=True)
da ci kanoniczny JSON, dzięki czemu będziesz mieć pewność, że oba dyktanda są równoważne. To zależy również od tego, co próbujesz osiągnąć. Gdy tylko wartość nie będzie JSON możliwa do serializacji, zakończy się niepowodzeniem. Dla tych, którzy twierdzą, że jest nieefektywny, spójrz na projekt ujson.Funkcja jest w porządku IMO, przejrzysta i intuicyjna. Ale żeby dać ci (inną) odpowiedź, oto moje przejście:
Może być przydatny dla ciebie lub kogokolwiek innego ...
EDYTOWAĆ:
Stworzyłem rekurencyjną wersję powyższej. Nie widziałem tego w innych odpowiedziach
źródło
Aby sprawdzić, czy dwa dykty są takie same w kluczach i wartościach:
Jeśli chcesz zwrócić różne wartości, napisz je inaczej:
Trzeba by to nazwać dwa razy, tj
źródło
Kod
Test
źródło
Proste porównanie z == powinno wystarczyć w dzisiejszych czasach (python 3.8). Nawet jeśli porównasz te same dykty w innej kolejności (ostatni przykład). Najlepsze jest to, że do tego nie potrzebujesz pakietu innej firmy.
źródło
Spóźnienie w mojej odpowiedzi jest lepsze niż nigdy!
Porównaj Not_Equal jest bardziej wydajne niż porównywanie Equal. W związku z tym dwa dyktaty nie są sobie równe, jeśli w kluczu nie znaleziono żadnych kluczowych wartości w jednym dykcie. Poniższy kod bierze pod uwagę, że być może porównujesz domyślny słownik i dlatego używa get zamiast getitem [].
Użycie pewnego rodzaju wartości losowej jako domyślnej w wywołaniu get równej pobieranemu kluczowi - na wypadek, gdyby dyktony miały wartość None jako wartość w jednym dycie, a ten klucz nie istnieje w drugim. Również warunek get! = Jest sprawdzany przed nieuwzględnieniem wydajności, ponieważ sprawdzane są klucze i wartości z obu stron jednocześnie.
źródło
Korzystam z tego rozwiązania, które działa idealnie dla mnie w Python 3
Porównuje dict, list i wszelkie inne typy, które same implementują operatora „==”. Jeśli chcesz porównać coś innego, musisz dodać nową gałąź w „drzewie drzewa”.
Mam nadzieję, że to pomaga.
źródło
dla python3:
źródło
Oto kolejna opcja:
Jak widać, dwa identyfikatory są różne. Ale operatory porównywania bogatego wydają się załatwić sprawę:
źródło
W PyUnit istnieje metoda, która pięknie porównuje słowniki. Przetestowałem go za pomocą następujących dwóch słowników i robi dokładnie to, czego szukasz.
Nie polecam importowania
unittest
do kodu produkcyjnego. Moja myśl jest taka, że źródło PyUnit może zostać ponownie opracowane tak, aby działało w produkcji. Wykorzystuje,pprint
które „ładne” drukuje słowniki. Łatwo jest dostosować ten kod, aby był „gotowy do produkcji”.źródło
zobacz obiekty widok słownika: https://docs.python.org/2/library/stdtypes.html#dict
W ten sposób możesz odjąć dictView2 od dictView1, a to zwróci zestaw par klucz / wartość, które są różne w dictView2:
Możesz przecinać, łączyć, różnicę (pokazaną powyżej), różnicę symetryczną tych obiektów widoku słownika.
Lepszy? Szybciej? - nie jestem pewien, ale stanowi część standardowej biblioteki - co czyni go dużym plusem pod względem przenośności
źródło
Poniższy kod pomoże ci porównać listę dykt w Pythonie
źródło
źródło
W Pythonie 3.6 można to zrobić jako:
zmienna ret będzie prawdziwa, jeśli wszystkie elementy dict_1 obecne w dict_2
źródło
Oto moja odpowiedź: użyj rekursywnego sposobu:
Mam nadzieję, że to pomaga!
źródło
Dlaczego nie po prostu iterować po jednym słowniku i sprawdzać drugi w trakcie procesu (zakładając, że oba słowniki mają te same klucze)?
Wynik:
źródło
Najłatwiejszym (i jednym z bardziej niezawodnych) do wykonania głębokiego porównania dwóch słowników jest ich serializacja w formacie JSON, sortowanie kluczy i porównanie wyników łańcucha:
źródło
źródło
json.dumps
jest deterministyczne przy ustawieniach domyślnych).