函数式思维(二)-- 为何你想不到用 reduce
栏目: JavaScript · 发布时间: 6年前
内容简介:上次我写了一篇简单介绍函数式思维的文章,我们组的同学看了之后表示很感兴趣,希望我有空多写写这方面的内容,然后表示他能想到用数组的 map,但是想不到 reduce。我想这可能也是个普遍现象,因为在对 FP(函数式编程)接触不多的同学来讲,脑海中对 map 的印象,可能基本等同于循环,而对 reduce 就相对陌生。但其实呢,reduce 是个比 map、flatMap 啥的更通用的函数,你可以用 reduce 轻易地实现其他函数。我们先实现一下 reduce:JS 里
上次我写了一篇简单介绍函数式思维的文章,我们组的同学看了之后表示很感兴趣,希望我有空多写写这方面的内容,然后表示他能想到用数组的 map,但是想不到 reduce。我想这可能也是个普遍现象,因为在对 FP(函数式编程)接触不多的同学来讲,脑海中对 map 的印象,可能基本等同于循环,而对 reduce 就相对陌生。但其实呢,reduce 是个比 map、flatMap 啥的更通用的函数,你可以用 reduce 轻易地实现其他函数。
我们先实现一下 reduce:
// foldl const reduce = (reducer, acc) => arr => { // reduceRight: const x = arr.pop(); const x = arr.shift(); if (!x) return acc; return reduce(reducer, reducer(acc, x))(arr); }; 复制代码
JS 里 Array.prototype.reduce 跟我这个稍有不同,它的 reducer 可以接收四个参数(比我的版本多了 currentIndex 和 array),某种程度上我的实现更 FP 一点,有 currentIndex 这个参数,基本就告诉我们它的实现是通过循环做的,而且这多出来的两个参数在什么场景下会真的必须用到呢?我想是在你 reduce 的过程中还在改变原数组的情况下,所以需要从参数拿到更新后的 array(也就意味着产生了副作用),这本身就很不 FP,不可变性和无副作用是 FP 的重要特性,就算我们在真实开发中无法完全做到,但既然是在谈 reduce,那总该尽量避免。所以个人感觉 JS 的这个 reduce 从 FP 的角度看的话有点不伦不类。
然后再解释下为啥我的 reduce 不是直接接收三个参数,而要用部分应用的形式,先接收两个,返回一个接收一个参数的函数呢?是为了复用,我们看个例子,用 reduce 实现一个 sum 函数,把数组里的元素都累加起来:
const arr = [1, 2, 3]; // 下文所有的 arr 都是这个 const sum = reduce((acc, x) => acc + x, 0); sum(arr); // => 6 复制代码
reduce 在接收不同的 reducer 和 acc 的时候会返回不同的函数,这里是返回 sum,是不是就很顺。而如果 reduce 是一个接收三个参数的函数,那 sum 就得是 const sum = (arr) => reduce((acc, x) => acc + x, 0, arr)
,也不是不可以,但比较丑陋。
接下来我们用 reduce 实现数组的其他方法:length、map、flatMap、includes、find
// JS 的 Array.length 跟我这个实现不一样, // arr[100] = 1,arr.length 就为 101 了,因为 JS 的 Array 本质是对象 const length = reduce(acc => acc + 1, 0); length(arr); // => 3 const map = func => reduce((acc, x) => [...acc, func(x)], []); map(x => x + 1)(arr); // => [2, 3, 4] const flatMap = func => reduce((acc, x) => [...acc, ...func(x)], []); flatMap(x => [x + 1])(arr); // => [2, 3, 4] const includes = element => reduce((acc, x) => acc || (x === element), false); includes(1)(arr); // => true // 找到第一个符合条件的元素返回,否则返回 undefined const find = func => reduce((acc, x) => acc || (func(x) ? x : undefined), undefined); find(x => x > 2)(arr); // => 3 复制代码
我们有时候处理字符串,也会想用到 reduce、map 啥的,那我们就给 String.prototype 加上:
// string String.prototype.reduce = function (reducer, acc) { return reduce(reducer, acc)(this.split('')); }; String.prototype.map = function (func) { return map(func)(this.split('')).join(''); }; const str = '123'; str.reduce((acc, x) => acc + Number(x), 0); // => 6 str.map(x => Number(x) + 1); // => '234' 复制代码
emmmmmmm……就这样吧。
以上所述就是小编给大家介绍的《函数式思维(二)-- 为何你想不到用 reduce》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- EOS DDOS攻击,你想不到的这12小时
- 90%的项目经理都想不到,沟通成本原来可以这么小
- 只有想不到,「99」种扩展Jupyter功能的好方法
- 没想到吧!竟有你绝对想不到的黑客追踪神技术
- 最难学的十大编程语言,Java只排第三,第一你绝对想不到!
- 你绝对想不到年过40岁的程序员可以有多么牛X!,程序员出路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Data Structures and Algorithms in Java
Robert Lafore / Sams / 2002-11-06 / USD 64.99
Data Structures and Algorithms in Java, Second Edition is designed to be easy to read and understand although the topic itself is complicated. Algorithms are the procedures that software programs use......一起来看看 《Data Structures and Algorithms in Java》 这本书的介绍吧!
CSS 压缩/解压工具
在线压缩/解压 CSS 代码
html转js在线工具
html转js在线工具