Estou tentando avaliar ((x == a and y == b) or (x == b and y == a))
em Python, mas parece um pouco detalhado. Existe uma maneira mais elegante?
python
boolean-logic
LetEpsilonBeLessThanZero
fonte
fonte
x,y, a,b
: são ints / floats / strings, objetos arbitrários ou o quê? Se eles fossem do tipo interno e fosse possível manter ambosx,y
ea,b
na ordem classificada, você poderia evitar o segundo ramo. Observe que a criação de um conjunto fará com que cada um dos quatro elementosx,y, a,b
seja hash, que pode ou não ser trivial ou ter uma implicação no desempenho, dependendo inteiramente do tipo de objeto que eles são.((x == a and y == b) or (x == b and y == a))
pode parecer estranho, mas 1) sua intenção é clara e inteligível para todos os programadores não-Python, não enigmáticos 2) os intérpretes / compiladores sempre lidam bem com isso e, essencialmente, nunca podem resultar em código de baixo desempenho, ao contrário do alternativas. Portanto, 'mais elegante' também pode ter desvantagens sérias.Respostas:
Se os elementos forem laváveis, você poderá usar conjuntos:
fonte
{1, 1, 2} == {1, 2, 2}
. Nesse ponto, você precisasorted
ouCounter
.Eu acho que o melhor que você pode obter é empacotá-los em tuplas:
Ou talvez envolva isso em uma pesquisa definida
Desde que foi mencionado por alguns comentários, fiz alguns intervalos e tuplas e conjuntos parecem ter um desempenho idêntico aqui quando a pesquisa falha:
Embora as tuplas sejam realmente mais rápidas quando a pesquisa for bem-sucedida:
Eu escolhi usar um conjunto porque estou fazendo uma pesquisa de associação e, conceitualmente, um conjunto é mais adequado para esse caso de uso do que uma tupla. Se você mediu uma diferença significativa entre as duas estruturas em um caso de uso específico, siga a mais rápida. Não acho que o desempenho seja um fator aqui.
fonte
if (a, b) in ((x, y), (y, x))
?set
solução na resposta à solução de tupla do @Brilliand?As tuplas o tornam um pouco mais legível:
Isso dá uma pista: estamos verificando se a sequência
x, y
é igual à sequência,a, b
mas ignorando a ordem. Isso é apenas definir a igualdade!fonte
,
cria uma tupla, não uma lista. so(x, y)
e(a, b)
são tuplas, iguais ax, y
ea, b
.list
tipo Python . Editado porque de fato isso era confuso.Se os itens não forem editáveis, mas suportarem comparações de pedidos, você pode tentar:
fonte
complex
por exemplo.A maneira mais elegante, na minha opinião, seria
Essa é uma maneira melhor do que usar conjuntos, ou seja
{a, b} == {y, x}
, conforme indicado em outras respostas, porque não precisamos pensar se as variáveis são hashable.fonte
Se estes são números, você pode usar
(x+y)==(a+b) and (x*y)==(a*b)
.Se esses itens são comparáveis, você pode usar
min(x,y)==min(a,b) and max(x,y)==max(a,b)
.Mas
((x == a and y == b) or (x == b and y == a))
é claro, seguro e mais geral.fonte
Como generalização para mais de duas variáveis, podemos usar
itertools.permutations
. Isso é em vez denós podemos escrever
E, claro, a versão de duas variáveis:
fonte
O(N*N!)
; Para 11 variáveis, isso pode levar mais de um segundo para terminar. (Eu publiquei um método mais rápido, mas ainda é necessárioO(N^2)
, e começa a demorar mais de um segundo em 10 mil variáveis; portanto, parece que isso pode ser feito rápido ou geralmente (wrt. Hashability / orderability), mas não os dois: P)Você pode usar tuplas para representar seus dados e verificar a inclusão de conjuntos, como:
fonte
Você já tem a solução mais legível . Existem outras maneiras de expressar isso, talvez com menos caracteres, mas são menos fáceis de ler.
Dependendo do que os valores realmente representam, sua melhor aposta é encerrar o cheque em uma função com um nome falante . Como alternativa ou além disso, é possível modelar os objetos x, ye a, b, cada um em objetos dedicados de classe superior, que você poderá comparar com a lógica da comparação em um método de verificação de igualdade de classe ou em uma função personalizada dedicada.
fonte
Parece que o OP estava preocupado apenas com o caso de duas variáveis, mas como o StackOverflow também é para quem procurar a mesma pergunta posteriormente, tentarei abordar o caso genérico aqui com mais detalhes; Uma resposta anterior já contém uma resposta genérica usando
itertools.permutations()
, mas esse método leva aO(N*N!)
comparações, pois existemN!
permutações comN
itens cada. (Essa foi a principal motivação para esta resposta)Primeiro, vamos resumir como alguns dos métodos das respostas anteriores se aplicam ao caso genérico, como motivação para o método apresentado aqui. Vou usar
A
para me referir(x, y)
eB
me referir(a, b)
, que podem ser tuplas de comprimento arbitrário (mas igual).set(A) == set(B)
é rápido, mas só funciona se os valores forem hasháveis e você pode garantir que uma das tuplas não contenha valores duplicados. (Por exemplo{1, 1, 2} == {1, 2, 2}
, como apontado por @ user2357112 na resposta de @Daniel Mesejo)O método anterior pode ser estendido para trabalhar com valores duplicados usando dicionários com contagens, em vez de conjuntos: (Isso ainda tem a limitação de que todos os valores precisam ser laváveis, portanto, por exemplo, valores mutáveis como
list
não funcionarão)sorted(A) == sorted(B)
não requer valores laváveis, mas é um pouco mais lento e requer valores ordenáveis. (Então, por exemplocomplex
, não funcionará)A in itertools.permutations(B)
não requer valores laváveis ou ordenáveis, mas, como já mencionado, possuiO(N*N!)
complexidade; portanto, mesmo com apenas 11 itens, pode demorar um segundo para terminar.Então, existe uma maneira de ser tão geral, mas é consideravelmente mais rápido? Por que sim, verificando "manualmente" se existe a mesma quantidade de cada item: (A complexidade deste é
O(N^2)
, portanto, também não é bom para entradas grandes; na minha máquina, 10 mil itens podem demorar um segundo - mas com entradas menores, como 10 itens, isso é tão rápido quanto os outros)Para obter o melhor desempenho, pode-se tentar
dict
primeiro o método baseado em, retornar aosorted
método baseado em falha devido a valores laváveis e, finalmente, voltar aocount
método baseado em falha também devido a valores desordenados.fonte