Ich versuche, eine benutzerdefinierte Filtermethode zu schreiben, die eine beliebige Anzahl von kwargs verwendet und eine Liste zurückgibt, die die Elemente einer datenbankähnlichen Liste enthält, die diese kwargs enthält .
Nehmen wir zum Beispiel an d1 = {'a':'2', 'b':'3'}
und d2
= dasselbe. d1 == d2
führt zu True. Aber nehmen wir an d2
= dasselbe plus eine Reihe anderer Dinge. Meine Methode muss in der Lage sein zu erkennen, ob d1 in d2 ist , aber Python kann das nicht mit Wörterbüchern tun.
Kontext:
Ich habe eine Wortklasse, und jedes Objekt hat Eigenschaften wie word
, definition
, part_of_speech
, und so weiter. Ich möchte in der Lage sein, eine Filtermethode in der Hauptliste dieser Wörter aufzurufen, wie z Word.objects.filter(word='jump', part_of_speech='verb-intransitive')
. Ich kann nicht herausfinden, wie diese Schlüssel und Werte gleichzeitig verwaltet werden. Dies könnte jedoch außerhalb dieses Kontexts eine größere Funktionalität für andere Personen haben.
quelle
d1.viewitems() <= d2.viewitems()
. Timeit-Läufe zeigten eine dreifache Leistungsverbesserung. Wenn nicht hashbar, führt selbst die Verwendungiteritems()
anstelle vonitems()
zu einer etwa 1,2-fachen Verbesserung. Dies wurde mit Python 2.7 durchgeführt.items()
werden einfache Ansichten anstelle von Kopien zurückgegeben. Es ist keine weitere Optimierung erforderlich.In Python 3 können Sie
dict.items()
eine satzartige Ansicht der diktierten Elemente erhalten. Mit dem<=
Operator können Sie dann testen, ob eine Ansicht eine "Teilmenge" der anderen ist:Verwenden Sie in Python 2.7 Folgendes, um
dict.viewitems()
dasselbe zu tun:In Python 2.6 und niedriger benötigen Sie eine andere Lösung, z. B
all()
.:quelle
d1.items() <= d2.items()
d1.items() <= d2.items()
werden tatsächlich zwei Tupellisten ohne bestimmte Reihenfolge verglichen, sodass das Endergebnis wahrscheinlich nicht zuverlässig ist. Aus diesem Grund wechsle ich zu @blubberdiblubs Antwort.d1.items() <= d2.items()
ist undefiniertes Verhalten. Es ist nicht in den offiziellen Dokumenten dokumentiert und wird vor allem nicht getestet: github.com/python/cpython/blob/… Dies ist also implementierungsabhängig.collections.abc.Set
verfügbar"Hinweis für Personen, die dies für Unit-Tests benötigen: Es gibt auch eine
assertDictContainsSubset()
Methode in PythonsTestCase
Klasse.http://docs.python.org/2/library/unittest.html?highlight=assertdictcontainssubset#unittest.TestCase.assertDictContainsSubset
Es ist jedoch in 3.2 veraltet, nicht sicher warum, vielleicht gibt es einen Ersatz dafür.
quelle
Für Schlüssel und Werte überprüfen Sie Folgendes:
set(d1.items()).issubset(set(d2.items()))
Wenn Sie nur die Schlüssel überprüfen müssen:
set(d1).issubset(set(d2))
quelle
d1={'a':1,'b':2}; d2={'a':2,'b':1}
-> das zweite Snippet wird zurückkehrenTrue
...{'a', 'b'}
ist in der Tat eine Teilmenge von{'a', 'b'}
;)Der Vollständigkeit halber können Sie auch Folgendes tun:
Ich mache jedoch keinerlei Ansprüche hinsichtlich Geschwindigkeit (oder mangelnder Geschwindigkeit) oder Lesbarkeit (oder mangelnder Lesbarkeit).
quelle
small.viewitems() <= big.viewitems()
waren vielversprechend, aber mit einer Einschränkung: Wenn Ihr Programm auch unter Python 2.6 (oder sogar darunter) verwendet werden könnte,d1.items() <= d2.items()
werden tatsächlich zwei Listen von Tupeln ohne bestimmte Reihenfolge verglichen, sodass das Endergebnis wahrscheinlich sein wird nicht zuverlässig. Aus diesem Grund wechsle ich zu @blubberdiblubs Antwort. Upvoted.dict
als Basisklasse dient? Was ist, wenn es sich nicht wie ein verhältdict
? Was ist, wennsmall
undbig
Werte unterschiedlichen Typs an einem passenden Schlüssel enthalten, die sich immer noch wie diktieren verhalten?False
den Werten der übergebenen Diktate entspricht sind unterschiedlich für passende Schlüssel). Oder mit anderen Worten: Die Lösung für verschachtelte Dikte ist nicht unbedingt ein Drop-In-Ersatz, abhängig vom Anwendungsfall.Kontext:
quelle
Meine Funktion für den gleichen Zweck, rekursiv:
In Ihrem Beispiel
dictMatch(d1, d2)
sollte True zurückgegeben werden, auch wenn d2 andere Inhalte enthält. Außerdem gilt dies auch für niedrigere Ebenen:Anmerkungen: Es könnte eine noch bessere Lösung geben, die die
if type(pvalue) is dict
Klausel vermeidet und für eine noch größere Bandbreite von Fällen gilt (z. B. Listen von Hashes usw.). Auch die Rekursion ist hier nicht beschränkt. Verwenden Sie sie daher auf eigenes Risiko. ;)quelle
Hier ist eine Lösung, die auch in Listen und Mengen, die im Wörterbuch enthalten sind, ordnungsgemäß wiederholt wird. Sie können dies auch für Listen verwenden, die Diktate usw. enthalten.
quelle
Dieses scheinbar unkomplizierte Problem kostet mich ein paar Stunden Recherche, um eine 100% zuverlässige Lösung zu finden. Deshalb habe ich dokumentiert, was ich in dieser Antwort gefunden habe.
"Pythonic-Verbündeter" zu sprechen,
small_dict <= big_dict
wäre der intuitivste Weg, aber schade, dass es nicht funktioniert .{'a': 1} < {'a': 1, 'b': 2}
funktioniert anscheinend in Python 2, ist aber nicht zuverlässig, da die offizielle Dokumentation dies ausdrücklich anzeigt. Suche suchen "Andere Ergebnisse als Gleichheit werden konsistent aufgelöst, aber nicht anders definiert." in diesem Abschnitt . Ganz zu schweigen davon, dass der Vergleich von 2 Dikten in Python 3 zu einer TypeError-Ausnahme führt.Die zweitintuitivste Sache ist nur
small.viewitems() <= big.viewitems()
für Python 2.7 undsmall.items() <= big.items()
für Python 3. Aber es gibt eine Einschränkung: Es ist möglicherweise fehlerhaft . Wenn Ihr Programm möglicherweise unter Python <= 2.6 verwendet werden könnte,d1.items() <= d2.items()
werden tatsächlich zwei Tupellisten ohne bestimmte Reihenfolge verglichen, sodass das Endergebnis unzuverlässig ist und zu einem bösen Fehler in Ihrem Programm wird. Ich bin nicht daran interessiert, eine weitere Implementierung für Python <= 2.6 zu schreiben, aber ich fühle mich immer noch nicht wohl, dass mein Code einen bekannten Fehler enthält (selbst wenn er sich auf einer nicht unterstützten Plattform befindet). Also gebe ich diesen Ansatz auf.Ich beruhige mich mit der Antwort von @blubberdiblub (Gutschrift geht an ihn):
def is_subdict(small, big): return dict(big, **small) == big
Es sei darauf hingewiesen, dass diese Antwort auf dem
==
Verhalten zwischen Diktaten beruht , das im offiziellen Dokument klar definiert ist und daher in jeder Python-Version funktionieren sollte . Suche suchen:quelle
Hier ist eine allgemeine rekursive Lösung für das gegebene Problem:
HINWEIS: Der ursprüngliche Code in bestimmten Fällen fehlschlagen würde, Kredite für die Befestigung geht an @ olivier-Melançon
quelle
if not set(value) <= set(superset[key])
Wenn es Ihnen nichts ausmacht,
pydash
gibt esis_match
dort, was genau das tut:quelle
Ich weiß, dass diese Frage alt ist, aber hier ist meine Lösung, um zu überprüfen, ob ein verschachteltes Wörterbuch Teil eines anderen verschachtelten Wörterbuchs ist. Die Lösung ist rekursiv.
quelle
Diese Funktion funktioniert für nicht hashbare Werte. Ich denke auch, dass es klar und leicht zu lesen ist.
quelle
Eine kurze rekursive Implementierung, die für verschachtelte Wörterbücher funktioniert:
Dies verbraucht die a- und b-Wörter. Wenn jemand einen guten Weg kennt, dies zu vermeiden, ohne auf teilweise iterative Lösungen wie in anderen Antworten zurückzugreifen, sagen Sie es mir bitte. Ich würde einen Weg brauchen, um ein Diktat basierend auf einem Schlüssel in Kopf und Schwanz aufzuteilen.
Dieser Code ist als Programmierübung nützlicher und wahrscheinlich viel langsamer als andere Lösungen, die Rekursion und Iteration mischen. Die Lösung von @ Nutcracker ist ziemlich gut für verschachtelte Wörterbücher.
quelle
a
(und alle nachfolgenden ersten Werte) gefundenpopitem
. Es sollte auch andere Elemente auf derselben Ebene untersuchen. Ich habe zwei verschachtelte Wörter, bei denen die falsche Antwort zurückgegeben wird. (schwer ein zukunftssicheres Beispiel hier zu präsentieren, da es auf der Reihenfolge von beruhtpopitem
)