it-swarm.com.de

Elegante Art, Tupel-Arithmetik durchzuführen

Was ist die eleganteste und prägnanteste Methode (ohne meine eigene Klasse mit Operatorüberladung zu erstellen), um Tupel-Arithmetik in Python 2.7) durchzuführen?

Nehmen wir an, ich habe zwei Tupel:

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

Mein beabsichtigtes Ergebnis ist

c = a - b = (6, 6)

Ich benutze derzeit:

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

Ich habe auch versucht:

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

aber das Ergebnis war (6, 6, 6, 6). Ich glaube, dass das oben Genannte als verschachtelt für Schleifen funktioniert, was zu 4 Iterationen und 4 Werten im Ergebnis führt.

47
user1737647

Wenn Sie schnell suchen, können Sie numpy verwenden:

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

und wenn du es in einem Tupel behalten willst:

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

Eine Möglichkeit wäre,

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

Und itertools.imap kann als Ersatz für map dienen.

Natürlich können Sie auch andere Funktionen von operator bis add, mul, div usw. verwenden.

Aber ich würde ernsthaft in Betracht ziehen, in eine andere Datenstruktur zu wechseln, da ich nicht denke, dass diese Art von Problem für Tuples geeignet ist

32
Jared

Verwenden Sie Zip und einen Generatorausdruck:

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

Demo:

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

Verwenden itertools.izip für eine speichereffiziente Lösung.

hilfe zu 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

Genauso gut geht das auch ohne Import, obwohl Lambda oft unerwünscht ist:

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

Wenn Sie den Abstand zwischen zwei Punkten auf einer 2D-Koordinatenebene ermitteln möchten, sollten Sie den absoluten Wert der Subtraktion der Paare verwenden.

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

JFYI, Ausführungszeit in meinem Laptop in 100000-facher Iteration

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

betreiber sieht für mich eleganter aus.

2
Kohei Kawasaki

Als Ergänzung zu Kohei Kawasakis Antwort auf die Frage nach der Geschwindigkeit war die ursprüngliche Lösung tatsächlich die schnellste.

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

mein elementweiser Tupel-Rechenhelfer

unterstützte Operationen: +, -, /, *, d

operation = 'd' berechnet den Abstand zwischen zwei Punkten auf einer 2D-Koordinatenebene

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