Я пытаюсь оценить ((x == a and y == b) or (x == b and y == a))
в Python, но это кажется немного многословным. Есть ли более элегантный способ?
python
boolean-logic
LetEpsilonBeLessThanZero
источник
источник
x,y, a,b
: это целые / плавающие / строковые объекты, произвольные объекты или что? Если бы они были встроенными типами, и было возможно сохранить обаx,y
иa,b
в отсортированном порядке, то вы могли бы избежать второй ветви. Обратите внимание, что создание набора приведетx,y, a,b
к хешированию каждого из четырех элементов , что может быть или не быть тривиальным или влиять на производительность в зависимости от того, к какому типу объектов они относятся.((x == a and y == b) or (x == b and y == a))
может выглядеть юкки, но 1) его цель кристально ясна и понятна всем не-Python-программистам, а не загадочным 2) интерпретаторы / компиляторы всегда с этим справятся хорошо, и это, по сути, никогда не приведет к неэффективному коду, в отличие от альтернативы. Таким образом, у «более элегантных» тоже могут быть серьезные недостатки.Ответы:
Если элементы являются хэшируемыми, вы можете использовать наборы:
источник
{1, 1, 2} == {1, 2, 2}
, В этот момент вам нужноsorted
илиCounter
.Я думаю, что лучшее, что вы можете получить, - это упаковать их в кортежи:
Или, может быть, обернуть это в поиске набора
Так как это было упомянуто парой комментариев, я сделал несколько моментов, и кортежи и наборы, кажется, работают одинаково здесь, когда поиск не удался:
Хотя кортежи на самом деле быстрее при успешном поиске:
Я решил использовать набор, потому что я делаю поиск членства, и концептуально набор лучше подходит для этого варианта использования, чем кортеж. Если вы измерили существенное различие между двумя структурами в конкретном случае использования, выберите более быстрый вариант. Я не думаю, что производительность является фактором, хотя здесь.
источник
if (a, b) in ((x, y), (y, x))
, хотя?set
решение в ответе решению кортежа из @Brilliand?Кортежи делают его немного более читабельным:
Это дает подсказку: мы проверяем,
x, y
равна ли последовательность последовательности,a, b
но игнорируем порядок. Это просто установить равенство!источник
,
создает кортеж, а не список. так(x, y)
и(a, b)
есть кортежи, такие же какx, y
иa, b
.list
. Отредактировано, потому что действительно это сбивало с толку.Если элементы не могут быть хешируемыми, но поддерживают сравнения при сортировке, вы можете попробовать:
источник
complex
, например.Самый элегантный способ, на мой взгляд, был бы
Это лучший способ, чем использование множеств, т.
{a, b} == {y, x}
Е. Как указано в других ответах, потому что нам не нужно думать, являются ли переменные хэшируемыми.источник
Если это цифры, вы можете использовать
(x+y)==(a+b) and (x*y)==(a*b)
.Если это сопоставимые предметы, вы можете использовать
min(x,y)==min(a,b) and max(x,y)==max(a,b)
.Но
((x == a and y == b) or (x == b and y == a))
это ясно, безопасно и более общее.источник
В качестве обобщения более двух переменных мы можем использовать
itertools.permutations
. Это вместомы можем написать
И конечно две переменные версии:
источник
O(N*N!)
, Для 11 переменных это может занять более секунды, чтобы закончить. (Я опубликовал более быстрый метод, но он все еще занимаетO(N^2)
и начинает занимать более секунды для переменных 10k; так что, похоже, это можно сделать быстро или в целом (относительно хешабельности / упорядоченности), но не одновременно: P)Вы можете использовать кортежи для представления своих данных, а затем проверить их на включение, например:
источник
Вы уже получили самое читаемое решение . Есть и другие способы выразить это, возможно, с меньшим количеством символов, но они не так просты для чтения.
В зависимости от того, какие значения на самом деле представляют вашу лучшую ставку, стоит обернуть чек в функцию с говорящим именем . В качестве альтернативы или дополнения вы можете моделировать объекты x, y и a, b каждый в выделенных объектах более высокого класса, которые затем можно сравнить с логикой сравнения в методе проверки равенства классов или в специальной пользовательской функции.
источник
Кажется, что 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
не будут работать)sorted(A) == sorted(B)
не требует хешируемых значений, но немного медленнее, и вместо этого требует заказываемых значений. (Так, напримерcomplex
, не будет работать)A in itertools.permutations(B)
не требует хешируемых или заказываемых значений, но, как уже упоминалось, он имеетO(N*N!)
сложность, поэтому даже при наличии всего 11 элементов для завершения может потребоваться более секунды.Итак, есть ли способ быть общим, но сделать это значительно быстрее? Почему да, «вручную» проверяя, что есть одинаковое количество каждого элемента: (Сложность этого состоит в том
O(N^2)
, что это также не хорошо для больших входов; на моей машине 10 тысяч элементов могут занять более секунды - но с меньшие входы, например 10 элементов, это так же быстро, как и другие)Чтобы получить максимальную производительность, можно
dict
сначала попробовать методsorted
-based, вернуться кcount
методу -base, если это не удастся из-за необратимых значений, и, наконец, вернуться к методу -based, если он тоже не удастся из-за неупорядоченных значений.источник