2013-07-02 3 views
33

Qual è il modo più elegante e conciso (senza creare la mia classe con overloading dell'operatore) per eseguire aritmetica tupla in Python 2.7?Modo elegante per eseguire aritmetica di tuple

Diciamo che ho due tuple:

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

mio risultato previsto è

c = a - b = (6, 6) 

Attualmente uso:

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

Ho anche provato:

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

ma il risultato era (6, 6, 6, 6). Credo che quanto sopra funzioni come loop annidati con 4 iterazioni e 4 valori nel risultato.

+0

Se stai facendo un sacco di questi e non sono particolarmente bisogno di essere _tuples_ potresti guardare numpy –

risposta

39

Se siete alla ricerca di veloce, è possibile utilizzare NumPy:

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

e se si desidera mantenere in una tupla:

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

Uso zip e un generatore di espressione:

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

Dimostrazione:

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

Uso itertools.izip una soluzione efficiente della memoria.

aiuto su 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

Grazie per la risposta dettagliata! –

+0

Solo una nota su 'izip': In Python 3, la normale funzione' zip' funziona come 'izip' di Python 2, quindi puoi usare 'zip' come mostrano gli esempi in questa risposta. –

27

Una possibilità sarebbe quella,

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

E itertools.imap può servire come un sostituto per map.

Naturalmente è anche possibile utilizzare altre funzioni operator-add, mul, div, ecc

ma vorrei prendere in seria considerazione lo spostamento in un'altra struttura di dati in quanto non credo che questo tipo di problema, è adatto per tuple s

+0

Grazie. +1 per operatore e mappa. –

2

Questo può anche essere fatto altrettanto bene senza un'importazione a tutti, anche se lambda è spesso indesiderabile:

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

Se stai cercando di ottenere la distanza tra due punti sulla diciamo una coordinata 2d piano si dovrebbe usare il valore assoluto della sottrazione delle coppie.

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

mio elemento-saggio tupla helper aritmetica

operazioni supportate: +, -, /, *, d

funzionamento = 'd' calcola la distanza tra due punti su un 2D coordinate aereo

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))")