赞
踩
我们学习编程通常是从命令式编程起步的。比如说计算1~100的平方和,我们会这样写:
let result = 0
for (let i = 1; i <= 100; i++) {
result += i * i
}
这样写的好处是逻辑清楚,每一条语句的作用显而易见。但是随着代码量越来越多,其缺陷也渐渐凸显出来。
此时,便引出了另一种编程方法: 流式编程。流式编程和链式编程属于同一种东西,所以本文统一称为流式编程。本文不会深入讲解流式编程的底层实现,而是让大家能快速理解流式编程的思想,并上手写出简洁的代码。
一句话描述流式编程: 基于集合变换的编程。
那么什么是集合变换?又该怎么变换呢?
先来看一个例子: 找出一个数组中大于100的数。如果用面向过程的思想,我们会怎么做呢?
const raw = [1, 2, 5, 100, 121]
let result = []
for (const e of raw) {
if (e > 100) {
result.push(e)
}
}
这是我们从学习编程之初就形成的思维,现在我们从更高的抽象角度理解这个问题:
raw --过滤--> result
从原始数据到结果,实际上就是对原始集合进行了过滤的操作,留下大于100的数。因此,上面的代码可以这样改写:
const raw = [1, 2, 5, 100, 121]
const result = raw.filter(e => e > 100)
是不是变得十分简洁?其中的filter是过滤函数,es6数组自带的操作。不光是JS,python\java等很多语言都集成了流式编程的基本功能,我们可以很方便地实现各种高级功能。
这三个操作是流式编程里面用的最广泛的,还有groupBy、collect等操作留给读者自行研究
map, 元素映射。其作用是将原集合的每个元素,通过一个操作映射到目标集合。举个例子,求一个数组的平方,用map操作就是这样的:
const raw = [1, 2, 3]
const res = raw.map(e => e * e) // [1, 4, 9]
其底层实现是遍历每个元素,然后追加到新的数组里。
reduce, 元素合并。其作用是迭代地对两个元素进行合并操作。比如求一个数组的和,便可以这样写:
const raw = [1, 2, 3]
const sum = raw.reduce((x, y) => x + y) // 6
其底层实现是遍历每个元素,两两合并,然后将结果与下一个元素进行合并。
如: 1. temp = x[0] + x[1] 2. temp = temp + x[2] 3. temp = temp + x[3] …
filter,元素过滤。其作用是将满足条件的元素留存到另一个集合,比如求数组中小于100的数:
const raw = [1, 2, 3]
const res = raw.filter(e => e < 100)
其底层操作是遍历+if判断
流式编程还有另一个特点,那就是流函数执行之后,返回的也是一个流。这样的话,就可以完成更复杂的工作了。比如求数组中超过100,且其平方小于50000的平方和。用命令式写法咋写呢?
const raw = [1, 2, 4, 100, 122, 444]
let res = 0
for (const e of raw) {
if (e > 100 && e * e < 50000) {
res += e * e
}
}
虽然代码不多,但是各种判断混合在一起,影响整个代码逻辑的表达
那么用集合变换的思想,不难抽象为以下三步:
于是,用一句话便可以完成这个功能:
const raw = [1, 2, 100, 123]
const sum = (x, y) => x * y // 求和函数
// [raw] --> [大于100] --> [平方] --> [平方小于50000] --> [和]
const res = raw.map(e => e > 100).map(e => e * e).filter(e => e < 50000).reduce(sum)
流式编程有几大优势
有优势便必然有劣势
Java。 java8开始有了Stream和lambda表达式,用Stream和ParallelStream(并行版本)与lambda表达式(匿名函数)可以很方便地实现流式编程。
Python。python 原生的 列表推导式可以实现集合变换,但无法实现链式操作,因此不是很高效。我比较推荐 PyFunctional这个库,其包含了 map、reduce、filter这些基本的操作,还提供了 groupBy(聚合) 这类的高级函数。
https://scalafunctional.readthedocs.io/en/master/functional.html#streams-api
JS。js的Array自带map、reduce、fiter等函数,groupBy等需要自己扩展
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。