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 a O(N*N!)
comparações, pois existem N!
permutações com N
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)
e B
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)
def counts(items):
d = {}
for item in items:
d[item] = d.get(item, 0) + 1
return d
counts(A) == counts(B)
sorted(A) == sorted(B)
não requer valores laváveis, mas é um pouco mais lento e requer valores ordenáveis. (Então, por exemplo complex
, não funcionará)
A in itertools.permutations(B)
não requer valores laváveis ou ordenáveis, mas, como já mencionado, possui O(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)
def unordered_eq(A, B):
for a in A:
if A.count(a) != B.count(a):
return False
return True
Para obter o melhor desempenho, pode-se tentar dict
primeiro o método baseado em, retornar ao sorted
método baseado em falha devido a valores laváveis e, finalmente, voltar ao count
método baseado em falha também devido a valores desordenados.
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.