Сравнение всех элементов двух кортежей (со всеми функциями ())


Поэтому я знаю, что сравнения на кортежах работают лексикографически:

Кортежи и списки сравниваются лексикографически с помощью сравнения соответствующих элементов. Это означает, что для сравнения равных, каждый элемент должен сравнивать равные и две последовательности должны быть одного типа и иметь одинаковую длину. Если они не равны, то последовательности упорядочиваются так же, как и их первые отличающиеся элементы. Например, cmp ([1,2,x], [1,2,y]) возвращает то же самое, что СМР(Х,Y). Если соответствующего элемента не существует, то сначала упорядочивается более короткая последовательность (например, [1,2]

Итак, из этого:

>>> a = (100, 0)
>>> b = (50, 50)
>>> a > b
True

Но я хочу сравнить все элементы 2 кортежей по порядку, поэтому функционально я хочу что-то похожее (используя значения сверху):

>>> a > b
(True, False) #returned tuple containing each comparison
>>> all(a > b)
False

В качестве примера на практике, для чего-то вроде координат экрана, если вы хотите проверить, было ли что-то "внутри" экрана при (0,0), но сделали сравнение, как coord > (0,0), если бы координата x была больше 0, но координата y была меньше, она все равно возвращала бы true, что в данном случае не требуется.

Как своего рода дополнительный вопрос / обсуждение:
Я не уверен, почему сравнение 2 кортежей разных значений возвращается таким образом. Вам не дается никакого индекса, поэтому единственное, что вы получаете от сравнения кортежа (это не проверка равенства), - это то, что в какой-то момент в кортеже одно из сравнений бросит истинное или ложное значение, когда они будут не равный. Как ты можешь этим воспользоваться?

5 4

5 ответов:

Вы можете достичь этого с помощью понимания списка и встроенного zip:

>>> a = (100, 0)
>>> b = (50, 50)
>>> [(a > b) for a, b in zip(a,b)]
[True, False]

Вы можете использовать all() или any() в возвращаемом списке.

Замените a > b на tuple(i > j for i, j in zip(a,b)) во втором примере кода.

>>> a = (100, 0)
>>> b = (50, 50)
>>> tuple(i > j for i, j in zip(a,b))
(True, False)
>>> all(i > j for i, j in zip(a,b))
False

Вы можете рассмотреть возможность использования следующего векторизованного подхода , который обычно более эффективен и синтаксически / семантически очень ясен:

>>> import numpy
>>>
>>> a = (100, 0)
>>> b = (50, 50)
>>> numpy.array(a) > b
array([ True, False], dtype=bool)
>>> 
>>> (numpy.array(a) > b).any()
True
>>> (numpy.array(a) > b).all()
False
  • Numpy довольно производителен, и результирующие объекты выше также вставляют любые()/все() методы запроса, которые вы хотите. Если вы будете выполнять вектор-подобные операции (как предполагает ваш пример экранных координат), Вы можете рассмотреть возможность работы с 'a' и 'b' в виде массивов numpy, а не кортежей. Это приводит к тому, что наиболее эффективная реализация того, что вы ищете: нет необходимости в предварительном преобразовании, и циклы на основе Python заменяются эффективными циклами на основе numpy. Это стоит подчеркнуть, потому что существует два и потенциально три цикла: (1) цикл предварительной обработки во время преобразования (который можно исключить); (2) Цикл сравнения элементов по элементам; и (3) цикл запроса для ответа на вопрос any/all.

  • Обратите внимание, что я мог бы также создать массив numpy из 'b', но не сделал этого исключен один шаг преобразования и время предварительной обработки . Поскольку этот подход приводит к одному операнду быть и NumPy массив и кортеж, а последовательность расти, которые могут не привести к менее быстрому постатейного сравнения (который строгий и NumPy-К-и NumPy хорошо). Попробовать его. :)

Я чувствовал, что использование функций map и lambda отсутствовало в ответах

>>> a = (100, 0)
>>> b = (50, 50)
>>> all(map(lambda x,y: x > y, a, b)
False

Чтобы получить описанное поведение, попробуйте:

[ai > bi for ai,bi in zip(a,b)]

Причина, по которой сравнения кортежей возвращаются таким образом, заключается в том, что вы можете написать что-то вроде:

if a >= (0.,0.):
    print "a has only positive values"
else:
    print "a has at least one negative value"

Если Python вернет Кортеж, который вы описываете, то другого никогда не произойдет. Попробуйте

if (False,False):
    print "True!" # This is what is printed.
else:
    print "False!"

Надеюсь, это поможет.