Кажется, что OP касался только случая двух переменных, но, поскольку StackOverflow также предназначен для тех, кто ищет тот же вопрос позже, я попытаюсь рассмотреть здесь общий случай более подробно; Один предыдущий ответ уже содержит общий ответ с использованием itertools.permutations()
, но этот метод приводит к O(N*N!)
сравнениям, так как существуют N!
перестановки с N
элементами каждый. (Это была основная мотивация для этого ответа)
Во-первых, давайте подведем итог, как некоторые методы из предыдущих ответов применимы к общему случаю, в качестве мотивации для метода, представленного здесь. Я буду использовать A
для ссылки (x, y)
и B
ссылки (a, b)
, которые могут быть кортежами произвольной (но равной) длины.
set(A) == set(B)
быстрый, но работает только в том случае, если значения могут быть хэшируемыми, и вы можете гарантировать, что один из кортежей не содержит повторяющихся значений. (Например {1, 1, 2} == {1, 2, 2}
, как указал @ user2357112 в ответе @Daniel Mesejo)
Предыдущий метод может быть расширен для работы с дублирующимися значениями с помощью словарей со счетчиками вместо множеств: (Это все еще имеет ограничение, что все значения должны быть хешируемыми, например, изменяемые значения, такие как list
не будут работать)
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)
не требует хешируемых значений, но немного медленнее, и вместо этого требует заказываемых значений. (Так, например complex
, не будет работать)
A in itertools.permutations(B)
не требует хешируемых или заказываемых значений, но, как уже упоминалось, он имеет O(N*N!)
сложность, поэтому даже при наличии всего 11 элементов для завершения может потребоваться более секунды.
Итак, есть ли способ быть общим, но сделать это значительно быстрее? Почему да, «вручную» проверяя, что есть одинаковое количество каждого элемента: (Сложность этого состоит в том O(N^2)
, что это также не хорошо для больших входов; на моей машине 10 тысяч элементов могут занять более секунды - но с меньшие входы, например 10 элементов, это так же быстро, как и другие)
def unordered_eq(A, B):
for a in A:
if A.count(a) != B.count(a):
return False
return True
Чтобы получить максимальную производительность, можно dict
сначала попробовать метод sorted
-based, вернуться к count
методу -base, если это не удастся из-за необратимых значений, и, наконец, вернуться к методу -based, если он тоже не удастся из-за неупорядоченных значений.
x,y, a,b
: это целые / плавающие / строковые объекты, произвольные объекты или что? Если бы они были встроенными типами, и было возможно сохранить обаx,y
иa,b
в отсортированном порядке, то вы могли бы избежать второй ветви. Обратите внимание, что создание набора приведетx,y, a,b
к хешированию каждого из четырех элементов , что может быть или не быть тривиальным или влиять на производительность в зависимости от того, к какому типу объектов они относятся.