Wygląda na to, że OP zajmował się jedynie przypadkiem dwóch zmiennych, ale ponieważ StackOverflow jest również dla tych, którzy szukają tego samego pytania później, postaram się tutaj szczegółowo zająć przypadkiem ogólnym; Jedna poprzednia odpowiedź zawiera już ogólną odpowiedź itertools.permutations(), ale ta metoda prowadzi do O(N*N!)porównań, ponieważ istnieją N!permutacje z Nelementami. (To była główna motywacja tej odpowiedzi)
Najpierw podsumujmy, w jaki sposób niektóre metody z poprzednich odpowiedzi odnoszą się do przypadku ogólnego, jako motywację do metody przedstawionej tutaj. Będę używać Ado odwoływania się (x, y)i Bdo odniesienia (a, b), które mogą być krotkami o dowolnej (ale równej) długości.
set(A) == set(B)jest szybki, ale działa tylko wtedy, gdy wartości są haszowalne i możesz zagwarantować, że jedna z krotek nie zawiera żadnych zduplikowanych wartości. (Na przykład.{1, 1, 2} == {1, 2, 2} , Jak wskazał @ user2357112 w odpowiedzi @Daniel Mesejo)
Poprzednia metoda może zostać rozszerzona do pracy ze zduplikowanymi wartościami za pomocą słowników z licznikami zamiast zestawów: (To wciąż ma ograniczenie, że wszystkie wartości muszą być możliwe do skrótu, więc np. Zmienne wartości takie jak listnie będą działać)
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)nie wymaga wartości mieszających, ale jest nieco wolniejszy i zamiast tego wymaga wartości uporządkowanych. (Więc np. complexNie będzie działać)
A in itertools.permutations(B)nie wymaga wartości skrótu ani zamówień, ale jak już wspomniano, ma O(N*N!)złożoność, więc nawet przy 11 elementach ukończenie może zająć sekundę.
Czy istnieje sposób, aby być tak ogólnym, ale czy jest to znacznie szybsze? Dlaczego tak, „ręcznie” sprawdzając, czy jest taka sama ilość każdego elementu: (Złożoność tego jest O(N^2)taka, że nie jest to również dobre w przypadku dużych nakładów; na mojej maszynie 10 000 elementów może zająć sekundę - ale z mniejsze nakłady, takie jak 10 pozycji, jest tak samo szybki jak inne)
def unordered_eq(A, B):
for a in A:
if A.count(a) != B.count(a):
return False
return True
Aby uzyskać najlepszą wydajność, można dictnajpierw wypróbować metodę opartą na bazie , powrócić do sortedmetody opartej na bazie, jeśli to się nie powiedzie z powodu nieusuwalnych wartości, a na koniec wrócić do countmetody opartej na podstawie , jeśli to też się nie powiedzie z powodu nieuporządkowanych wartości.
x,y, a,b: czy są to ints / float / strings, dowolne obiekty, czy co? Gdyby były wbudowane typy i udało się zachować zarównox,yia,bposortowanych, wtedy można uniknąć drugiego oddziału. Zauważ, że utworzenie zestawu spowoduje, że każdy z czterech elementówx,y, a,bzostanie zaszyfrowany, co może, ale nie musi, być trywialne lub mieć wpływ na wydajność w zależności od tego, jakiego rodzaju są obiektami.