2013-07-02 4 views
33

Что является самым элегантным и лаконичным способом (без создания собственного класса с перегрузкой оператора) для выполнения арифметики кортежа в Python 2.7?Элегантный способ выполнения арифметики кортежа

Допустим, у меня есть два кортежа:

a = (10, 10) 
b = (4, 4) 

Мой предполагаемый результат является

c = a - b = (6, 6) 

Я в настоящее время используют:

c = (a[0] - b[0], a[1] - b[1]) 

Я также попытался:

c = tuple([(i - j) for i in a for j in b]) 

но результат был (6, 6, 6, 6). Я считаю, что выше работает как вложенное для циклов, что приводит к 4 итерациям и 4 значениям результата.

+0

Если вы делаете много из них, и им особо не нужно быть _tuples_, вы можете посмотреть на numpy –

ответ

39

Если вы ищете быстро, вы можете использовать NumPy:

>>> import numpy 
>>> numpy.subtract((10, 10), (4, 4)) 
array([6, 6]) 

, и если вы хотите сохранить его в виде кортежа:

>>> tuple(numpy.subtract((10, 10), (4, 4))) 
(6, 6) 
24

Используйте zip и выражение генератора:

c = tuple(x-y for x, y in zip(a, b)) 

Демонстрация:

>>> a = (10, 10) 
>>> b = (4, 4) 
>>> c = tuple(x-y for x, y in zip(a, b)) 
>>> c 
(6, 6) 

Использование itertools.izip для памяти эффективного решения.

помощь на zip:

>>> print zip.__doc__ 
zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)] 

Return a list of tuples, where each tuple contains the i-th element 
from each of the argument sequences. The returned list is truncated 
in length to the length of the shortest argument sequence. 
+0

Спасибо за подробный ответ! –

+0

Просто примечание на 'izip': в Python 3 регулярная функция' zip' работает как 'izip' Python 2, поэтому вы можете просто использовать' zip' в качестве примеров в этом показе ответов. –

27

Один из вариантов,

>>> from operator import sub 
>>> c = tuple(map(sub, a, b)) 
>>> c 
(6, 6) 

И itertools.imap может служить в качестве замены для map.

Конечно, вы можете также использовать другие функции от operator к add, mul, div и т.д.

Но я бы серьезно рассмотреть вопрос о переходе в другую структуру данных, так как я не думаю, что этот тип проблемы подходит для tuple s

+0

Спасибо. +1 для оператора и отображения. –

2

Это также может быть сделано так же, как хорошо без импорта вообще, хотя лямбда часто нежелательна:

tuple(map(lambda x, y: x - y, a, b)) 

Если вы ищете, чтобы получить расстояние между двумя точками на скажу координату 2d плоскости вы должны использовать абсолютное значение вычитания пар.

tuple(map(lambda x ,y: abs(x - y), a, b)) 
0

мой поэлементно кортеж арифметическая помощник

Поддерживаемые операции: +, -, /, *, д

операция = 'd' вычисляет расстояние между двумя точками на 2D координатной плоскости

def tuplengine(tuple1, tuple2, operation): 
    """ 
    quick and dirty, element-wise, tuple arithmetic helper, 
    created on Sun May 28 07:06:16 2017 
    ... 
    tuple1, tuple2: [named]tuples, both same length 
    operation: '+', '-', '/', '*', 'd' 
    operation 'd' returns distance between two points on a 2D coordinate plane (absolute value of the subtraction of pairs) 
    """ 
    assert len(tuple1) == len(tuple2), "tuple sizes doesn't match, tuple1: {}, tuple2: {}".format(len(tuple1), len(tuple2)) 
    assert isinstance(tuple1, tuple) or tuple in type(tuple1).__bases__, "tuple1: not a [named]tuple" 
    assert isinstance(tuple2, tuple) or tuple in type(tuple2).__bases__, "tuple2: not a [named]tuple" 
    assert operation in list("+-/*d"), "operation has to be one of ['+','-','/','*','d']" 
    return eval("tuple(a{}b for a, b in zip(tuple1, tuple2))".format(operation)) \ 
    if not operation == "d" \ 
     else eval("tuple(abs(a-b) for a, b in zip(tuple1, tuple2))") 
Смежные вопросы