在Python 2.7中执行元组算法的最优雅和简洁的方法是什么(不用运算符重载创建我自己的类)?
假设我有两个元组:
a = (10, 10)
b = (4, 4)
我的预期结果是
c = a - b = (6, 6)
我目前使用:
c = (a[0] - b[0], a[1] - b[1])
我也尝试过:
c = tuple([(i - j) for i in a for j in b])
但结果是(6, 6, 6, 6)
。我相信上面的工作是嵌套的for循环,导致结果中有4次迭代和4个值。
答案 0 :(得分:57)
如果你正在寻找快速,你可以使用numpy:
>>> import numpy
>>> numpy.subtract((10, 10), (4, 4))
array([6, 6])
如果你想把它保存在一个元组中:
>>> tuple(numpy.subtract((10, 10), (4, 4)))
(6, 6)
答案 1 :(得分:32)
一个选项是,
>>> from operator import sub
>>> c = tuple(map(sub, a, b))
>>> c
(6, 6)
itertools.imap
可以替代map
。
当然,您还可以使用operator
到add
,mul
,div
等其他功能。
但我会认真考虑进入另一个数据结构,因为我不认为这类问题适合tuple
s
答案 2 :(得分:27)
使用zip
和生成器表达式:
c = tuple(x-y for x, y in zip(a, b))
<强>演示:强>
>>> a = (10, 10)
>>> b = (4, 4)
>>> c = tuple(x-y for x, y in zip(a, b))
>>> c
(6, 6)
使用itertools.izip
获取内存有效的解决方案。
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.
答案 3 :(得分:3)
这也可以在没有导入的情况下完成,尽管lambda通常是不受欢迎的:
tuple(map(lambda x, y: x - y, a, b))
如果你想在2d坐标平面上得到两点之间的距离,你应该使用对的减法的绝对值。
tuple(map(lambda x ,y: abs(x - y), a, b))
答案 4 :(得分:2)
JFYI,我的笔记本电脑的执行时间为100000次迭代
-- Misc. info
select version();
>PostgreSQL 10.5 on x86_64-apple-darwin16.7.0, compiled by Apple LLVM version 9.0.0 (clang-900.0.39.2), 64-bit
:0.18578505516052246
np.subtract(a, b)
:
0.09348797798156738
tuple(x - y for x, y in zip(a, b))
:0.07900381088256836
tuple(map(lambda x, y: x - y, a, b))
:0.044342041015625
操作员对我来说看起来更优雅。
答案 5 :(得分:0)
我的元素智能元组算术助手
支持的操作:+, - ,/,*,d
operation ='d'计算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 ))")
答案 6 :(得分:0)
除了川崎浩平(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
>>>
答案 7 :(得分:0)
由于在您的问题中只有2个数字元组的示例,对于类似坐标的元组,使用简单的内置“复杂”类可能会很好:
const handleChange = (event, name) => {
const newAge = {...age, [name]: event.tatget.value};
setAge(newAge);
};