web-dev-qa-db-fra.com

Manière élégante d'effectuer l'arithmétique de Tuple

Quelle est la manière la plus élégante et concise (sans créer ma propre classe avec surcharge d'opérateur) pour effectuer l'arithmétique de Tuple en Python 2.7?

Disons que j'ai deux tuples:

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

Mon résultat escompté est

c = a - b = (6, 6)

J'utilise actuellement:

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

J'ai aussi essayé:

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

mais le résultat était (6, 6, 6, 6). Je crois que ce qui précède fonctionne comme une imbriquée pour les boucles résultant en 4 itérations et 4 valeurs dans le résultat.

47
user1737647

Si vous cherchez rapide, vous pouvez utiliser numpy:

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

et si vous voulez le garder dans un tuple:

>>> Tuple(numpy.subtract((10, 10), (4, 4)))
(6, 6)
60
vroomfondel

Une option serait,

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

Et itertools.imap peut servir de remplacement pour map.

Bien sûr, vous pouvez également utiliser d'autres fonctions de operator à add, mul, div, etc.

Mais j'envisagerais sérieusement de passer à une autre structure de données car je ne pense pas que ce type de problème soit adapté à Tuples

32
Jared

Utilisez Zip et une expression de générateur:

c = Tuple(x-y for x, y in Zip(a, b))

Démo:

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

Utilisation itertools.izip pour une solution efficace en mémoire.

aide sur 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.
27
Ashwini Chaudhary

Cela peut également être fait aussi bien sans importation, bien que lambda soit souvent indésirable:

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

Si vous cherchez à obtenir la distance entre deux points sur un plan de coordonnées 2d par exemple, vous devez utiliser la valeur absolue de la soustraction des paires.

Tuple(map(lambda x ,y: abs(x - y), a, b))
3
miigotu

JFYI, temps d'exécution dans mon ordinateur portable à 100 000 fois l'itération

np.subtract(a, b): 0,18578505516052246

Tuple(x - y for x, y in Zip(a, b)): 0,09348797798156738

Tuple(map(lambda x, y: x - y, a, b)): 0,07900381088256836

from operator import sub Tuple(map(sub, a, b)): 0,044342041015625

l'opérateur est plus élégant pour moi.

2
Kohei Kawasaki

En plus de la réponse de Kohei Kawasaki, pour la vitesse, la solution originale était en fait la plus rapide.

>>> timeit.timeit('Tuple(map(add, a, b))',number=1000000,setup='from operator import add; a=(10,11); b=(1,2)')
0.6502681339999867
>>> timeit.timeit('(a[0] - b[0], a[1] - b[1])',number=1000000,setup='from operator import add; a=(10,11); b=(1,2)')
0.19015854899998885
>>> 
0
Skidushe

mon aide arithmétique Tuple élément par élément

opérations prises en charge: +, -, /, *, d

operation = 'd' calcule la distance entre deux points sur un plan de coordonnées 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 ))")
0
internety