Ich versuche ((x == a and y == b) or (x == b and y == a))
in Python zu evaluieren , aber es scheint ein bisschen ausführlich zu sein. Gibt es einen eleganteren Weg?
python
boolean-logic
LetEpsilonBeLessThanZero
quelle
quelle
x,y, a,b
es sich handelt: Sind es Ints / Floats / Strings, beliebige Objekte oder was? Wenn sie builtin Typen waren und es war möglich , sowohl zu haltenx,y
unda,b
in sortierter Reihenfolge, dann könnte man den zweiten Zweig zu vermeiden. Beachten Sie, dass beim Erstellen eines Satzes jedes der vier Elementex,y, a,b
gehasht wird, was trivial sein kann oder nicht oder Auswirkungen auf die Leistung hat, je nachdem, um welche Art von Objekten es sich handelt.((x == a and y == b) or (x == b and y == a))
vielleicht yukky aussieht, aber 1) seine Absicht ist kristallklar und für alle Nicht-Python-Programmierer verständlich, nicht kryptisch. 2) Interpreten / Compiler werden immer gut damit umgehen und es kann im Gegensatz zu im Wesentlichen nie zu nicht performantem Code führen Alternativen. "Eleganter" kann also auch schwerwiegende Nachteile haben.Antworten:
Wenn die Elemente hashbar sind, können Sie Mengen verwenden:
quelle
{1, 1, 2} == {1, 2, 2}
. An diesem Punkt brauchen Siesorted
oderCounter
.Ich denke, das Beste, was Sie bekommen können, ist, sie in Tupel zu verpacken:
Oder wickeln Sie das in eine Set-Lookup ein
Gerade als es in einigen Kommentaren erwähnt wurde, habe ich einige Timings durchgeführt, und Tupel und Sets scheinen hier identisch zu sein, wenn die Suche fehlschlägt:
Obwohl Tupel tatsächlich schneller sind, wenn die Suche erfolgreich ist:
Ich habe mich für die Verwendung eines Sets entschieden, weil ich eine Mitgliedersuche durchführe, und konzeptionell passt ein Set besser zu diesem Anwendungsfall als ein Tupel. Wenn Sie in einem bestimmten Anwendungsfall einen signifikanten Unterschied zwischen den beiden Strukturen gemessen haben, wählen Sie die schnellere. Ich denke jedoch nicht, dass Leistung hier ein Faktor ist.
quelle
if (a, b) in ((x, y), (y, x))
?set
Lösung in der Antwort der Tupellösung von @Brilliand vorzuziehen?Tupel machen es etwas lesbarer:
Dies gibt einen Hinweis: Wir prüfen, ob die Sequenz
x, y
der Sequenz entsprichta, b
, ignorieren jedoch die Reihenfolge. Das ist nur Gleichheit!quelle
,
erstellt ein Tupel, keine Liste. so(x, y)
und(a, b)
sind Tupel, wiex, y
unda, b
.list
Typs. Bearbeitet, weil das in der Tat verwirrend war.Wenn die Elemente nicht hashbar sind, aber Bestellvergleiche unterstützen, können Sie Folgendes versuchen:
quelle
complex
Zum Beispiel.Der eleganteste Weg wäre meiner Meinung nach
Dies ist ein besserer Weg als die Verwendung von Mengen, dh
{a, b} == {y, x}
wie in anderen Antworten angegeben, da wir nicht darüber nachdenken müssen, ob die Variablen hashbar sind.quelle
Wenn dies Zahlen sind, können Sie verwenden
(x+y)==(a+b) and (x*y)==(a*b)
.Wenn dies vergleichbare Artikel sind, können Sie verwenden
min(x,y)==min(a,b) and max(x,y)==max(a,b)
.Ist
((x == a and y == b) or (x == b and y == a))
aber klar, sicher und allgemeiner.quelle
Als Verallgemeinerung auf mehr als zwei Variablen können wir verwenden
itertools.permutations
. Das ist stattwir können schreiben
Und natürlich die zwei variablen Versionen:
quelle
O(N*N!)
; Bei 11 Variablen kann dies eine Sekunde dauern. (Ich habe eine schnellere Methode veröffentlicht, aber sie dauert immer nochO(N^2)
und beginnt mit einer Sekunde für 10.000 Variablen. Es scheint also, dass dies entweder schnell oder allgemein (in Bezug auf Hashbarkeit / Bestellbarkeit) möglich ist, aber nicht beides: P)Sie können Tupel verwenden, um Ihre Daten darzustellen, und dann prüfen, ob sie festgelegt sind, z.
quelle
Sie haben bereits die am besten lesbare Lösung . Es gibt andere Möglichkeiten, dies auszudrücken, vielleicht mit weniger Zeichen, aber sie sind weniger einfach zu lesen.
Abhängig davon, was die Werte tatsächlich darstellen, ist es am besten, den Scheck in eine Funktion mit einem sprechenden Namen einzuwickeln . Alternativ oder zusätzlich können Sie die Objekte x, y und a, b jeweils in dedizierten Objekten höherer Klasse modellieren, die Sie dann mit der Logik des Vergleichs in einer Methode zur Überprüfung der Klassengleichheit oder einer dedizierten benutzerdefinierten Funktion vergleichen können.
quelle
Es scheint, dass sich das OP nur mit dem Fall von zwei Variablen befasst hat, aber da StackOverflow auch für diejenigen gedacht ist, die später nach derselben Frage suchen, werde ich versuchen, den allgemeinen Fall hier etwas detaillierter zu behandeln. Eine vorherige Antwort enthält bereits eine generische Antwort mit
itertools.permutations()
, aber diese Methode führt zuO(N*N!)
Vergleichen, da esN!
Permutationen mit jeweilsN
Elementen gibt. (Dies war die Hauptmotivation für diese Antwort)Lassen Sie uns zunächst zusammenfassen, wie einige der Methoden in früheren Antworten auf den generischen Fall als Motivation für die hier vorgestellte Methode zutreffen. Ich werde verwenden, um auf
A
zu verweisen(x, y)
und aufB
zu verweisen(a, b)
, was Tupel beliebiger (aber gleicher) Länge sein können.set(A) == set(B)
ist schnell, funktioniert aber nur, wenn die Werte hashbar sind und Sie garantieren können, dass eines der Tupel keine doppelten Werte enthält. (ZB{1, 1, 2} == {1, 2, 2}
wie von @ user2357112 unter @ Daniel Mesejos Antwort hervorgehoben)Die vorherige Methode kann erweitert werden, um mit doppelten Werten zu arbeiten, indem Wörterbücher mit Zählungen anstelle von Mengen verwendet werden: (Dies hat immer noch die Einschränkung, dass alle Werte hashbar sein müssen, z. B. veränderbare Werte wie
list
funktionieren nicht.)sorted(A) == sorted(B)
erfordert keine hashbaren Werte, ist jedoch etwas langsamer und erfordert stattdessen bestellbare Werte. (Also zBcomplex
nicht funktionieren)A in itertools.permutations(B)
Es sind keine hashbaren oder bestellbaren Werte erforderlich, aber wie bereits erwähnt, ist es komplexO(N*N!)
, sodass selbst bei nur 11 Elementen die Fertigstellung über eine Sekunde dauern kann.Gibt es also eine Möglichkeit, so allgemein zu sein, aber geht es erheblich schneller? Warum ja, indem "manuell" überprüft wird, ob von jedem Element die gleiche Menge vorhanden ist: (Die Komplexität dieses Elements ist
O(N^2)
so, dass dies auch für große Eingaben nicht gut ist. Auf meinem Computer können 10.000 Elemente eine Sekunde dauern - aber mit kleinere Eingaben, wie 10 Elemente, dies ist genauso schnell wie die anderen)Um die beste Leistung zu erzielen, sollten Sie
dict
zuerst diesorted
Methode -based ausprobieren, auf die -based-Methode zurückgreifen, wenn dies aufgrund nicht zerlegbarer Werte fehlschlägt, und schließlich auf diecount
-based-Methode zurückgreifen, wenn auch dies aufgrund nicht ordnbarer Werte fehlschlägt.quelle