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 N
elementami. (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ć A
do odwoływania się (x, y)
i B
do 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 list
nie 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. complex
Nie 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 dict
najpierw wypróbować metodę opartą na bazie , powrócić do sorted
metody opartej na bazie, jeśli to się nie powiedzie z powodu nieusuwalnych wartości, a na koniec wrócić do count
metody 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,y
ia,b
posortowanych, wtedy można uniknąć drugiego oddziału. Zauważ, że utworzenie zestawu spowoduje, że każdy z czterech elementówx,y, a,b
zostanie 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.