Estoy tratando de evaluar ((x == a and y == b) or (x == b and y == a))
en Python, pero parece un poco detallado. ¿Hay alguna forma más elegante?
python
boolean-logic
LetEpsilonBeLessThanZero
fuente
fuente
x,y, a,b
sean: ¿son ints / floats / strings, objetos arbitrarios o qué? Si fueran incorporada tipos y fue posible mantener tantox,y
ya,b
en forma ordenada, entonces usted podría evitar la segunda rama. Tenga en cuenta que la creación de un conjunto hará que cada uno de los cuatro elementosx,y, a,b
se mezcle, lo que podría o no ser trivial o tener una implicación de rendimiento dependiendo completamente de qué tipo de objetos sean.((x == a and y == b) or (x == b and y == a))
puede parecer desagradable, pero 1) su intención es clara e inteligible para todos los programadores que no son de Python, no crípticos 2) los intérpretes / compiladores siempre lo manejarán bien y, esencialmente, nunca puede dar como resultado un código no funcional. alternativas. Entonces, 'más elegante' también puede tener serias desventajas.Respuestas:
Si los elementos son hashable, puede usar conjuntos:
fuente
{1, 1, 2} == {1, 2, 2}
. En ese punto, necesitassorted
oCounter
.Creo que lo mejor que puedes obtener es empaquetarlos en tuplas:
O, tal vez envuelva eso en una búsqueda establecida
Solo desde que fue mencionado por un par de comentarios, hice algunos tiempos, y las tuplas y los conjuntos parecen funcionar de manera idéntica aquí cuando falla la búsqueda:
Aunque las tuplas son realmente más rápidas cuando la búsqueda tiene éxito:
Elegí usar un conjunto porque estoy haciendo una búsqueda de membresía, y conceptualmente un conjunto es mejor para ese caso de uso que una tupla. Si midió una diferencia significativa entre las dos estructuras en un caso de uso particular, vaya con la más rápida. Sin embargo, no creo que el rendimiento sea un factor aquí.
fuente
if (a, b) in ((x, y), (y, x))
?set
solución en la respuesta a la solución de tupla de @Brilliand?Las tuplas lo hacen un poco más legible:
Esto da una pista: estamos verificando si la secuencia
x, y
es igual a la secuenciaa, b
pero ignorando el orden. Eso es solo establecer la igualdad!fuente
,
crea una tupla, no una lista. so(x, y)
y(a, b)
son tuplas, igual quex, y
ya, b
.list
tipo Python . Editado porque de hecho esto era confuso.Si los elementos no son compartibles, pero admiten comparaciones de pedidos, puede intentar:
fuente
complex
por ejemplo.La forma más elegante, en mi opinión, sería
Esta es una mejor manera que usar conjuntos, es decir
{a, b} == {y, x}
, como se indica en otras respuestas porque no necesitamos pensar si las variables son hashaable.fuente
Si estos son números, puedes usarlos
(x+y)==(a+b) and (x*y)==(a*b)
.Si se trata de elementos comparables, puede usar
min(x,y)==min(a,b) and max(x,y)==max(a,b)
.Pero
((x == a and y == b) or (x == b and y == a))
es claro, seguro y más general.fuente
Como generalización a más de dos variables que podemos usar
itertools.permutations
. Eso es en lugar depodemos escribir
Y, por supuesto, las dos versiones variables:
fuente
O(N*N!)
; Para 11 variables, esto puede tomar más de un segundo para terminar. (Publiqué un método más rápido, pero aún así tomaO(N^2)
, y comienza a tomar más de un segundo en 10k variables; por lo tanto, parece que esto se puede hacer rápido o en general (wrt. Hashability / orderability), pero no ambos: P)Puede usar tuplas para representar sus datos y luego verificar la inclusión de conjuntos, como:
fuente
Ya tienes la solución más legible . Hay otras formas de expresar esto, quizás con menos caracteres, pero son menos fáciles de leer.
Dependiendo de lo que los valores representen realmente, su mejor apuesta es envolver el cheque en una función con un nombre de voz . Alternativamente o además, puede modelar los objetos x, y y a, b cada uno en objetos dedicados de clase superior que luego puede comparar con la lógica de la comparación en un método de verificación de igualdad de clase o una función personalizada dedicada.
fuente
Parece que el OP solo estaba preocupado por el caso de dos variables, pero dado que StackOverflow también es para aquellos que buscan la misma pregunta más adelante, intentaré abordar el caso genérico aquí con cierto detalle; Una respuesta anterior ya contiene una respuesta genérica usando
itertools.permutations()
, pero ese método lleva aO(N*N!)
comparaciones, ya que hayN!
permutaciones conN
elementos cada una. (Esta fue la principal motivación para esta respuesta)Primero, resumamos cómo algunos de los métodos en respuestas anteriores se aplican al caso genérico, como motivación para el método presentado aquí. Usaré
A
para referirme(x, y)
yB
para referirme(a, b)
, que pueden ser tuplas de longitud arbitraria (pero igual).set(A) == set(B)
es rápido, pero solo funciona si los valores son hashables y puede garantizar que una de las tuplas no contenga ningún valor duplicado. (Por ejemplo{1, 1, 2} == {1, 2, 2}
, como señaló @ user2357112 bajo la respuesta de @Daniel Mesejo)El método anterior se puede ampliar para trabajar con valores duplicados mediante el uso de diccionarios con recuentos, en lugar de conjuntos: (Esto todavía tiene la limitación de que todos los valores deben ser hashables, por ejemplo, los valores mutables como
list
no funcionarán)sorted(A) == sorted(B)
no requiere valores hashables, pero es un poco más lento y requiere valores ordenables en su lugar. (Entonces, por ejemplocomplex
, no funcionará)A in itertools.permutations(B)
no requiere valores hashables u ordenables, pero como ya se mencionó, tieneO(N*N!)
complejidad, por lo que incluso con solo 11 elementos, puede llevar más de un segundo terminar.Entonces, ¿hay alguna manera de ser tan general, pero hacerlo considerablemente más rápido? Por qué sí, al verificar "manualmente" que hay la misma cantidad de cada elemento: (La complejidad de este es
O(N^2)
, por lo que tampoco es bueno para entradas grandes; en mi máquina, 10k elementos pueden tomar más de un segundo, pero con entradas más pequeñas, como 10 elementos, esto es tan rápido como los otros)Para obtener el mejor rendimiento, es posible que primero desee probar el
dict
método basado, recurrir alsorted
método basado si eso falla debido a valores no compartibles y, finalmente, recurrir alcount
método basado si eso también falla debido a valores no ordenados.fuente