2012-08-24 127 views
5

是否有任何允许Python 3中的元组进行元素操作的内置函数?如果没有,那么执行这些操作的“pythonic”方法是什么?Python中的元组的元素操作

示例:我想获取ab之间的百分比差异,并将它们与某个阈值th进行比较。

>>> a = (1, 2, 4) 
>>> b = (1.1, 2.1, 4.1) 
>>> # compute pd = 100*abs(a-b)/a = (10.0, 5.0, 2.5) 
>>> th = 3 
>>> # test threshold: pd < th => (False, False, True) 
+0

我们在谈论地图功能吗? http://docs.python.org/release/3.1.5/library/functions.html#map – bpgergo

+0

结合zip? http://docs.python.org/release/3.1.5/library/functions.html#zip – bpgergo

回答

5

地图功能

>>> a = (1, 2, 4) 
>>> b = (1.1, 2.1, 4.1) 
>>> map(lambda a,b: 100*abs(a-b)/a < 3, a, b) 
[False, False, True] 

编辑

当然不是地图的

,您可以使用列表解析,像BrenBarn做http://docs.python.org/tutorial/datastructures.html#nested-list-comprehensions

EDIT 2拉链删除,感谢帝斯曼指出来的是不需要压缩

+2

这里你不需要'zip';你可以写'map(lambda a,b:100 * abs(a-b)/ a <3,a,b)'。 (注意这个函数接受两个参数,而不是一个2元组。) – DSM

+0

'map(lambda(a,b):100 * abs(ab)/ a <3,a,b)'=>'TypeError:只需要1个参数(给出2个)' – bpgergo

+0

@DSM可能但可能不应该。我厌恶允许通过重载将另一个高阶函数合并到另一个函数中的快捷方式(在LINQ中很常见,例如'.First(cond)'而不是'.Where(cond).First()'),因为它永远不明显我*其中*操作隐含(地图?zip?过滤器?别的?)。 – delnan

1

我不知道这样的操作,也许有些的Python的函数编程功能将工作(图吗?减少?),虽然组建一个list comprehension(或发电机如果不需要名单)比较直截了当:

[100*abs(j-b[i])/j < 3 for i,j in enumerate(a)] 
[False, False, True] 

感谢@delnan用于指出一个非常好的简化原始,更明确的/详细的版本:

[True if 100*abs(j-b[i])/j < 3 else False for i,j in enumerate(a)] 
+3

'如果100 * abs(jb [i])/ j <3否则为真否则为false * - > 100 * abs( jb [i])/ j <3' – delnan

+0

@delnan啊..明白了!非常好!! ..谢谢,我会更新答案。 – Levon

+0

@delnan'bool'似乎并不需要 – Levon

9

没有内建的方法,但有一个非常简单的方法:

[f(aItem, bItem) for aItem, bItem in zip(a, b)] 

。 。 。 f是你想要应用元素的功能。对于您的情况:

[100*abs(aItem - bItem)/aItem < 3 for aItem, bItem in zip(a, b)] 

如果你发现自己这个做了很多,尤其是长元组,你可能想看看Numpy,它提供了矢量操作的全功能的系统,其中许多常见的载体功能(基本操作,触发函数等)应用元素。

+1

+1表示numpy –

0

我要说的Python化的方法是使用列表理解:

a = (1, 2, 4)b = (1.1, 2.1, 4.1)

然后,在一条线:

TEST = [100*abs(a[i]-b[i])/a[i] > th for i in range(len(A))] 
+0

这将评估A和B的笛卡尔积的fn,而不是元素。 – DSM

+0

@DSM oops,已更正。 –

0
def pctError(observed, expected): 
    return (observed-expected)/expected * 100.0 

a = (1, 2, 4) 
b = (1.1, 2.1, 4.1) 
th = 3 

pctErrors = map(lambda t:pctError(*t), zip(a,b)) 
# returns [-9.091, -4.76, -2.44] 

map(lambda x: x < th, pctErrors) 
[x < th for x in pctErrors] 
# both return [True, True, True] 

# or if you always need absolute % errors 
map(lambda x: abs(x) < th, pctErrors) 
[abs(x) < th for x in pctErrors] 
# both return [False, False, True] 
4

为什么不使用NumPy?

import numpy as np 
a = np.array([1,2,4]) 
b = np.array([1.1, 2.1, 4.1]) 

pd = 100*abs(a-b)/a # result: array([ 10. , 5. , 2.5]) 
th = 3 
pd < th # result: array([False, False, True], dtype=bool)