Python-elementweise Tupeloperationen wie sum

99

Gibt es überhaupt eine Möglichkeit, Tupeloperationen in Python so auszuführen?

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(4,4,4)

anstatt:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(1,2,3,3,2,1)

Ich weiß, dass es so funktioniert, weil die __add__und __mul__Methoden so definiert sind. Der einzige Weg wäre also, sie neu zu definieren?

Rodrigo
quelle

Antworten:

137
import operator
tuple(map(operator.add, a, b))
Ironfroggy
quelle
4
Ich würde sagen, dies ist die pythonischste Lösung.
Matthew Schinckel
3
Nur dass map () halb veraltet ist. Unter artima.com/weblogs/viewpost.jsp?thread=98196 finden Sie einen Artikel von Guido, in dem erwähnt wird, wie eine Karte besser als Listenverständnis geschrieben werden kann.
Adam Parkin
Es explodiert auch, wenn a & b nicht die gleiche Anzahl von Elementen enthält oder nicht "addierbar" ist (Beispiel:map(operator.add, (1,2), ("3", "4"))
Adam Parkin
22
tuple([item1 + item2 for item1, item2 in zip(a, b)])wäre das Äquivalent als Listenverständnis.
Adam Parkin
11
@AdamParkin, das Verständnis der Generatoren ist noch besser tuple(item1 + item2 for item1, item2 in zip(a, b)).
Cristian Ciupitu
118

Mit allen eingebauten ..

tuple(map(sum, zip(a, b)))
Triptychon
quelle
2
Dies scheint die einfachere und überlegenere Antwort zu sein. Warum wird es nicht akzeptiert?
Marc Cenedella
15
es ist gut, aber technisch nicht das, wonach gefragt wird, weil die Karte eine Liste zurückgibt, kein Tupel ... also:tuple(map(sum,zip(a,b))
Ben
3
Die Syntax ist mystisch.
Anatoly Techtonik
2
Der Vorteil dieses ist, dass Sie es erweitern können auf:tuple(map(sum,zip(a,b, c))
Andy Hayden
32

Diese Lösung erfordert keinen Import:

tuple(map(lambda x, y: x + y, tuple1, tuple2))
Boaz Shvartzman
quelle
2
Diese Lösung ist auch schneller als die andere Ein-Liner-Lösung ohne Import ( map(sum, zip(a, b)))
Air
20

Kombiniert die ersten beiden Antworten mit einer Optimierung des Codes von ironfroggy, sodass ein Tupel zurückgegeben wird:

import operator

class stuple(tuple):
    def __add__(self, other):
        return self.__class__(map(operator.add, self, other))
        # obviously leaving out checking lengths

>>> a = stuple([1,2,3])
>>> b = stuple([3,2,1])
>>> a + b
(4, 4, 4)

Hinweis: Verwenden von self.__class__anstelle von stuple, um die Unterklasse zu vereinfachen.

Dana
quelle
18
from numpy import *

a = array( [1,2,3] )
b = array( [3,2,1] )

print a + b

gibt array([4,4,4]).

Siehe http://www.scipy.org/Tentative_NumPy_Tutorial

Mike
quelle
7
Dies wird funktionieren, aber es ist etwas schwierig, numpy nur für eine einfache Additionsoperation zu importieren.
11

Das Generatorverständnis könnte anstelle der Karte verwendet werden. Die integrierte Kartenfunktion ist nicht veraltet, aber für die meisten Menschen weniger lesbar als das Verständnis von Listen / Generatoren / Diktaten. Daher würde ich empfehlen, die Kartenfunktion im Allgemeinen nicht zu verwenden.

tuple(p+q for p, q in zip(a, b))
Jaehyun Yeom
quelle
6

einfache Lösung ohne Klassendefinition, die Tupel zurückgibt

import operator
tuple(map(operator.add,a,b))
DemonEye
quelle
6

Alle Generatorlösung. Ich bin mir nicht sicher über die Leistung (itertools ist jedoch schnell)

import itertools
tuple(x+y for x, y in itertools.izip(a,b))
Mike
quelle
3

Ja. Sie können integrierte Typen jedoch nicht neu definieren. Sie müssen sie unterordnen:

Klasse MyTuple (Tupel):
    def __add __ (Selbst, Andere):
         if len (self)! = len (other):
             Erhöhen Sie ValueError ("Tupellängen stimmen nicht überein")
         Rückgabe von MyTuple (x + y für (x, y) in zip (self, other))
Doug
quelle
Aber dann können Sie die Tupelsyntax nicht verwenden.
Airportyh
3

Noch einfacher und ohne Verwendung der Karte können Sie dies tun

>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)
LetsPlayYahtzee
quelle
1

Ich klassifiziere derzeit die "Tupel" -Klasse, um +, - und * zu überladen. Ich finde, es macht den Code schön und das Schreiben des Codes einfacher.

class tupleN(tuple):
    def __add__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x+y for x,y in zip(self,other))
    def __sub__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x-y for x,y in zip(self,other))
    def __mul__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x*y for x,y in zip(self,other))


t1 = tupleN((1,3,3))
t2 = tupleN((1,3,4))
print(t1 + t2, t1 - t2, t1 * t2, t1 + t1 - t1 - t1)
(2, 6, 7) (0, 0, -1) (1, 9, 12) (0, 0, 0)
user2012588
quelle
-1

Für den Fall, dass jemand eine Liste von Tupeln mitteln muss:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))
ytutow
quelle