这三个高阶函数比较简单,但也特别常用。他们提供的抽象分别是
- map -> 变换
- filter -> 筛选
- reduce -> 归并
这三个函数只需要了解了就能够立即运用到自己的代码中,所以了解以下还是比较有用的。
map
转换一组值,但是该函数只是提供转换的一个抽象,如何转换需要由使用者提供,例如:
def square(x):
return x * x
l = range(10)
print(list(map(square, l)))
本篇代码皆以python为例,不再赘述。
这里的map第一个参数表明序列中的指应该如何变换,第二个参数则是需要变换的数据结构
filter
筛选一组值,只有当条件通过项目才会返回
def condition(x):
return x % 2 == 0
l = range(10)
print(list(filter(condition, l)))
reduce
将一组数据转换为单个数据
def sum(x, y):
return x + y
l = range(10)
print(reduce(sum, l))
总结
可以很容易发现事实上我们的循环大多数时候都在对线性结构作以下三种操作:变换,筛选,归并。而这三个函数只是将这三种操作抽象了出来。
filter和map的第一个参数是一个只有一个参数的函数,filter需要一个判断者,而map需要一个变换者。
reduce的第一个参数是一个两个参数的函数,reduce将每次将序列中的前两个值交给他,让后将这两个值替换为该函数的返回值,序列将越来越短小,直到最后只剩一个值,该函数还接受第三个参数作为第一个值。
可以看到在打印这filter, map函数的返回值之前,都用转换为了list,这是因为这两个函数都是惰性求值,值只有在用到的时候才会被求取,所以返回的是一个可迭代的对象。如果我们自己实现这两个函数当然可以直接让他们返回一个迭代器。
这三个函数在js,java中都有。用法相同。不同java通过Stream引入了这三个操作,这是因为他是一门纯粹的面向对象的语言(现在也不那么纯粹了),如果需要加入这三个方法,只有三个选项:
- 修改已有的序列类型添加实现
- 增加新类型
- 静态方法
一有序列类型上增加函数式接口大概是工作量太大,别否决,静态方法不符合面向对象的哲学,也别否决,所以增加新类型了。(PS:我猜的)