您的位置:首页 > 编程语言 > Python开发

python filter/map/reduce

2015-08-12 14:48 357 查看
Python内建的
filter()
函数用于过滤序列。

filter()
接收一个函数和一个序列。和
map()
不同的时,
filter()
把传入的函数依次作用于每个元素,然后根据返回值是
True
还是
False
决定保留还是丢弃该元素。

例如,在一个list中,删掉偶数,只保留奇数,可以这么写:
def is_odd(n):
return n % 2 == 1

filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
# 结果: [1, 5, 9, 15]


把一个序列中的空字符串删掉,可以这么写:
def not_empty(s):
return s and s.strip()

filter(not_empty, ['A', '', 'B', None, 'C', '  '])
# 结果: ['A', 'B', 'C']


可见用
filter()
这个高阶函数,关键在于正确实现一个“筛选”函数。

Python内建了
map()
reduce()
函数。

如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on Large Clusters”,你就能大概明白map/reduce的概念。

我们先看map。
map()
函数接收两个参数,一个是函数,一个是序列,
map
将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个list
[1, 2, 3, 4, 5, 6, 7, 8, 9]
上,就可以用
map()
实现如下:



现在,我们用Python代码实现:
>>> def f(x):
...     return x * x
...
>>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]


map()
传入的第一个参数是
f
,即函数对象本身。

你可能会想,不需要
map()
函数,写一个循环,也可以计算出结果:
L = []
for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
L.append(f(n))
print L


的确可以,但是,从上面的循环代码,能一眼看明白“把f(x)作用在list的每一个元素并把结果生成一个新的list”吗?

所以,
map()
作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:
>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
['1', '2', '3', '4', '5', '6', '7', '8', '9']


只需要一行代码。

再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)


比方说对一个序列求和,就可以用reduce实现:
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25


当然求和运算可以直接用Python内建函数
sum()
,没必要动用reduce。

但是如果要把序列
[1, 3, 5, 7, 9]
变换成整数13579,reduce就可以派上用场:
>>> def fn(x, y):
...     return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579


这个例子本身没多大用处,但是,如果考虑到字符串
str
也是一个序列,对上面的例子稍加改动,配合
map()
,我们就可以写出把
str
转换为
int
的函数:
>>> def fn(x, y):
...     return x * 10 + y
...
>>> def char2num(s):
...     return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579


整理成一个
str2int
的函数就是:
def str2int(s):
def fn(x, y):
return x * 10 + y
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
return reduce(fn, map(char2num, s))


还可以用lambda函数进一步简化成:
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]

def str2int(s):
return reduce(lambda x,y: x*10+y, map(char2num, s))


也就是说,假设Python没有提供
int()
函数,你完全可以自己写一个把字符串转化为整数的函数,而且只需要几行代码!

lambda函数的用法在后面介绍
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: