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?

Antworten:


137
import operator
tuple(map(operator.add, a, b))

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

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

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.



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

6

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

import operator
tuple(map(operator.add,a,b))

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

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

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)

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)

-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))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.