Python中的 Map,Filter 和 Reduce用法
接收函数为参数或者把函数作为结果返回的函数是高阶函数。
Map,Filter和Reduce是函数式编程的范例。 它们使程序员可以编写更简单,更短的代码,而不必担心诸如循环和分支之类的复杂问题。
这三个函数可以将一个函数应用于多个可迭代对象。 map()和filter()是Python内置的(在__builtins__模块中),不需要导入。 但是reduce()在functools模块中,因此需要导入。
filter()
filter() 函数用于过滤列表中的元素,并且返回一个由所有符合要求的元素所构成的列表。它接收一个函数和一个序列,把函数作用在序列的每个元素上,然后根据返回值是True还是False决定保留还是丢弃该元素。
它具有以下语法:
filter(func, iterable)
关于filter(),需要注意以下几点:
必须使用func参数才能返回布尔类型。 如果不是,filter()仅返回传递给它的可迭代对象。 另外,由于仅需要一个可迭代的函数,因此隐含的是func必须仅接受一个参数。
filter()通过func传递可迭代对象中的每个元素,并仅返回评估为True的那些元素。
filter()返回的是一个迭代器。
例子1:保留奇数列表
>>> mylist = list(range(10))
>>> list(filter(lambda x: x % 2 == 1, mylist))
[1, 3, 5, 7, 9]
例子2:保留小于0的数
>>> number_list = range(-5, 5)
>>> less_than_zero = filter(lambda x: x < 0, number_list)
>>> print(list(less_than_zero))
[-5, -4, -3, -2, -1]
例子3:回文(palindrome)检测器。 从候选回文的元组(可迭代对象)中过滤掉属于回文的单词。
“回文”是单词、词组或序列,其向后读取与向前读取相同。
>>> dromes = ("demigod", "rewire", "madam", "freer", "anutforajaroftuna", "kiosk")
>>> palindromes = list(filter(lambda w: w == w[::-1], dromes))
>>> palindromes
['madam', 'anutforajaroftuna']
map()
map()会将⼀个函数映射到⼀个输入列表的所有元素上。这是它的规范:
map(function_to_apply, list_of_inputs)
map()函数传入一个函数和一个序列,并把函数作用到序列的每个元素上,返回一个可迭代对象。
大多数时候,我们要把列表中所有元素⼀个个的传递给⼀个函数,并收集输出。比如
items = [1, 2, 3, 4, 5]
squared = []
for i in items:
squared.append(i ** 2)
map()函数可以让用⼀种简单⽽漂亮的⽅式来实现。
items = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, items))
还有更多的例子:
>>> list(map(lambda x: x % 2, mylist))
[1, 0, 1, 0, 1, 0, 1, 0, 1]
>>> list(map(lambda x: x * 2, mylist))
[2, 4, 6, 8, 10, 12, 14, 16, 18]
多数时候,我们使用匿名函数来配合map()。 此外map()不仅可以于⼀列表的输⼊, 甚⾄可以用于⼀个列表的函数。比如:
def add(x):
return x + x
def multiply(x):
return x * x
>>> funcs = [add, multiply]
>>> for i in range(5):
... value = map(lambda x: x(i), funcs)
... print(list(value)) # map()返回一个迭代器!
[0, 0]
[2, 1]
[4, 4]
[6, 9]
[8, 16]
filter()函数类似于一个 for 循环,但它是一个内置函数,速度更快。
事实上,在 Python 3 中,map() 和 filter() 虽然还是内置函数,但是由于引入了列表推导和生成器表达式,它们变得没那么重要了。列表推导或生成器表达式具有 map 和 filter 两个函数的功能,而且更易于阅读。
在 Python 3 中,map() 和 filter() 返回生成器,因此现在它们的直接替代品是生成器表达式。
reduce()
当需要对一个列表进行一些计算并返回结果时,reduce()是个非常有用的函数。
reduce()函数用于递归计算。reduce() 将两个参数的函数从初始参数开始累积地应用于可迭代对象的元素。 reduce()函数同样需要传入一个函数和一个序列。它具有以下语法:
reduce(func, iterable[, initial])
其中
func是对iterable中的每个元素累积应用的函数,而initial是在计算中置于iterable元素之前的可选值,并且在iterable为空时用作默认值。
func需要两个参数,第一个是iterable中的第一个元素(如果未提供initial)。 第二个是iterable中的第二个元素。 如果提供了initial,则它将成为func的第一个参数,而iterable中的第一个元素将成为第二个元素。
reduce()将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce() 中的 function函数 (有两个参数)先对集合中的第1和2个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
例如:
from functools import reduce
reduce(lambda x, y: x + y, range(101))
reduce()的应用:
一行代码搞定计算所有元素的积:
reduce(lambda x, y: x * y, range(1, 10))
计算列表中所有元素的最大值:
reduce(lambda x, y: x if x > y else y, [1, 2, 3, 4])
现在有一个列表:[3, 5, 8, 1]对应的是3581的每一个数字,要从这个列表计算出原来的数,可以这样做:
reduce(lambda x, y: x * 10 + y, [3, 5, 8, 1])
在 Python 2 中,reduce() 是内置函数,但是在 Python 3 中放到 functools模块里了。这个函数最常用于求和,但现在最好使用内置的sum函数。
总结
可以看出,上面的三个函数与匿名函数相结合使用,可以写出强大简洁的代码。