Python 执行元组算术的优雅方式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17418108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:09:27  来源:igfitidea点击:

Elegant way to perform tuple arithmetic

pythonpython-2.7numpytuples

提问by

What is the most elegant and concise way (without creating my own class with operator overloading) to perform tuple arithmetic in Python 2.7?

在 Python 2.7 中执行元组算术的最优雅和简洁的方法是什么(无需创建我自己的带有运算符重载的类)?

Lets say I have two tuples:

假设我有两个元组:

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

My intended result is

我的预期结果是

c = a - b = (6, 6)

I currently use:

我目前使用:

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

I also tried:

我也试过:

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

but the result was (6, 6, 6, 6). I believe the above works as a nested for loops resulting in 4 iterations and 4 values in the result.

但结果是(6, 6, 6, 6)。我相信上述内容作为嵌套的 for 循环工作,导致结果中有 4 次迭代和 4 个值。

采纳答案by vroomfondel

If you're looking for fast, you can use numpy:

如果你正在寻找快速,你可以使用 numpy:

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

and if you want to keep it in a tuple:

如果你想把它保存在一个元组中:

>>> tuple(numpy.subtract((10, 10), (4, 4)))
(6, 6)

回答by Ashwini Chaudhary

Use zipand a generator expression:

使用zip和生成器表达式:

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)

Use itertools.izipfor a memory efficient solution.

使用itertools.izip的内存有效的解决方案。

help on zip:

帮助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.

回答by Jared

One option would be,

一种选择是,

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

And itertools.imapcan serve as a replacement for map.

并且itertools.imap可以作为map.

Of course you can also use other functions from operatorto add, mul, div, etc.

当然,你也可以使用其他的功能operatoraddmuldiv等。

But I would seriously consider moving into another data structure since I don't think this type of problem is fit for tuples

但我会认真考虑转向另一种数据结构,因为我认为这种类型的问题不适合tuples

回答by miigotu

This can also be done just as nicely without an import at all, although lambda is often undesirable:

这也可以在完全没有导入的情况下很好地完成,尽管 lambda 通常是不可取的:

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

If you are looking to get the distance between two points on say a 2d coordinate plane you should use the absolute value of the subtraction of the pairs.

如果您想获得二维坐标平面上两点之间的距离,您应该使用对减法的绝对值。

tuple(map(lambda x ,y: abs(x - y), a, b))

回答by internety

my element-wise tuple arithmetic helper

我的逐元素元组算术助手

supported operations: +, -, /, *, d

支持的操作:+、-、/、*、d

operation = 'd' calculates distance between two points on a 2D coordinate plane

operation = 'd' 计算二维坐标平面上两点之间的距离

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

回答by Kohei Kawasaki

JFYI, execution time in my laptop in 100000 times iteration

JFYI,100000 次迭代在我的笔记本电脑中的执行时间

np.subtract(a, b): 0.18578505516052246

np.subtract(a, b): 0.18578505516052246

tuple(x - y for x, y in zip(a, b)): 0.09348797798156738

tuple(x - y for x, y in zip(a, b)): 0.09348797798156738

tuple(map(lambda x, y: x - y, a, b)): 0.07900381088256836

tuple(map(lambda x, y: x - y, a, b)): 0.07900381088256836

from operator import sub tuple(map(sub, a, b)): 0.044342041015625

from operator import sub tuple(map(sub, a, b)): 0.044342041015625

operator looks more elegant for me.

运算符对我来说看起来更优雅。

回答by Kohei Kawasaki

As an addition to Kohei Kawasaki's answer, for speed, the original solution was actually the fastest (For a length two tuple at least).

作为对 Kohei Kawasaki 的回答的补充,对于速度,原始解决方案实际上是最快的(至少对于长度为二元组)。

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

回答by Rustam A.

Since in your question there only examples of 2-number-tuples, for such coordinate-like tuples, you may be good with simple built-in "complex" class:

由于在您的问题中只有 2-number-tuples 的例子,对于这种类似坐标的元组,您可能对简单的内置“复杂”类很好:

>>> a=complex(7,5)
>>> b=complex(1,2)
>>> a-b
>>> c=a-b
>>> c
(6+3j)
>>> c.real
6.0
>>> c.imag
3.0