Opérations de tuple élément par élément Python comme sum

99

Existe-t-il de toute façon pour que les opérations de tuple en Python fonctionnent comme ceci:

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

au lieu de:

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

Je sais que cela fonctionne comme ça parce que les méthodes __add__et __mul__sont définies pour fonctionner comme ça. Alors le seul moyen serait de les redéfinir?

Rodrigo
la source

Réponses:

137
import operator
tuple(map(operator.add, a, b))
ironfroggy
la source
4
Je dirais que c'est la solution la plus pythonique.
Matthew Schinckel
3
Sauf que map () est semi-obsolète. Voir artima.com/weblogs/viewpost.jsp?thread=98196 pour un article de Guido où il mentionne comment la carte est mieux écrite en tant que compréhension de liste.
Adam Parkin
Il explose également si a & b ne contiennent pas le même nombre d'éléments, ou ne sont pas "addables" (ex:map(operator.add, (1,2), ("3", "4"))
Adam Parkin
22
tuple([item1 + item2 for item1, item2 in zip(a, b)])serait l'équivalent d'une compréhension de liste.
Adam Parkin
11
@AdamParkin, la compréhension des générateurs est encore meilleure tuple(item1 + item2 for item1, item2 in zip(a, b)).
Cristian Ciupitu
118

Utilisation de tous les éléments intégrés.

tuple(map(sum, zip(a, b)))
Triptyque
la source
2
Cela semble être la réponse la plus simple et la meilleure. Pourquoi n'est-il pas accepté?
Marc Cenedella
15
c'est bien, mais techniquement pas ce qui est demandé car la map renvoie une liste, pas un tuple ... donc:tuple(map(sum,zip(a,b))
Ben
3
La syntaxe est mystique.
anatoly techtonik
2
L'avantage de celui-ci est que vous pouvez l'étendre à:tuple(map(sum,zip(a,b, c))
Andy Hayden
32

Cette solution ne nécessite pas d'importation:

tuple(map(lambda x, y: x + y, tuple1, tuple2))
Boaz Shvartzman
la source
2
Cette solution est également plus rapide que l'autre solution à une seule ligne sans importation ( map(sum, zip(a, b)))
Air
20

En quelque sorte combiné les deux premières réponses, avec un ajustement du code d'ironfroggy pour qu'il renvoie un tuple:

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)

Remarque: utilisez self.__class__au lieu de stuplepour faciliter le sous-classement.

Dana
la source
18
from numpy import *

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

print a + b

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

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

Mike
la source
7
Cela fonctionnera, mais c'est un peu lourd d'importer numpy juste pour une simple opération d'addition.
11

La compréhension du générateur pourrait être utilisée à la place de la carte. La fonction de carte intégrée n'est pas obsolète mais elle est moins lisible pour la plupart des gens que la compréhension de liste / générateur / dict, donc je vous recommande de ne pas utiliser la fonction de carte en général.

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

solution simple sans définition de classe qui retourne tuple

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

Toute solution de générateur. Je ne suis pas sûr des performances (itertools est rapide, cependant)

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

Oui. Mais vous ne pouvez pas redéfinir les types intégrés. Vous devez les sous-classer:

class MyTuple (tuple):
    def __add __ (soi, autre):
         si len (soi)! = len (autre):
             lever ValueError ("les longueurs de tuple ne correspondent pas")
         retourne MyTuple (x + y pour (x, y) dans zip (self, other))
Doug
la source
mais alors vous ne pouvez pas utiliser la syntaxe de tuple.
airportyh
3

encore plus simple et sans utiliser de carte, vous pouvez le faire

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

Je sous-classe actuellement la classe "tuple" pour surcharger +, - et *. Je trouve que cela rend le code beau et l'écriture du code plus facile.

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)
utilisateur2012588
la source
-1

Au cas où quelqu'un aurait besoin de faire la moyenne d'une liste de tuples:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))
Ytutow
la source