少侠,你的transducer到了,请拿去装逼~

766 阅读8分钟

image

少侠们好~

上次和大家分享了一个关于降低遍历数组时所耗能量的技巧。

通过这个技巧,我们把一开始的代码:

image

变成了下面这样:

image

而且在最后,我说了这次会给大家分享一个新的武器,也就是下面这个东西:

image

这个东西可不好弄,费了挺大劲,不过还好,最后总算给弄来了,

那么,

有的少侠可能要问了:

“天辰,既然这样,你费这么劲弄来的这个武器到底有啥用?”

少侠!

既然你诚心诚意的发问了,

我就大发慈悲的告诉你!

为了防止世界被破坏,

为了维护世界的和平,

贯彻爱与真实的邪恶,

潇洒又迷人的反派角色

天辰……dreamer……

“喂,天辰,你是不是走错片场了?!!!”

“。。。。。。。。”

重新回到刚才的问题来,

这里正确答案应该可能是:

1、上面最后的代码虽然降低了遍历次数,但是,逻辑比较耦合,不利于扩展,transduce可以解决这个问题,在保持性能的前提下,也有比较好的扩展性。

2、transducer依赖了很多关键知识点,学习transducer能够帮助少侠你更好的理解它们。

3、学习transducer能够很好的锻炼抽象思维,帮助少侠们打开脑洞。

、能够用来装逼~

好了,

现在开始进入正题~

为了理解transduce, 我们首先需要理解reduce,

我们先来回顾一下上次最后时刻的代码:

image

在最后,我们只用一个reduce函数,就实现了过滤,映射,以及最后的叠加操作。

少侠你应该也发现了,

reduce函数比我们想象中的更厉害,

那么,

既然reduce函数这么强大,我们能不能用它来代替map或者filter函数呢?

对于这个问题,

有的少侠可能会说了,

“切~,既然天辰你都这么问了,那答案肯定是能啊,要不然你问它干嘛?”

对于这类少侠,天辰想说的是:

“就TM你话多!~”

但是~

我们确实可以用reduce实现map和filter一样的效果。

还是从简单的例子开始:

这有一个数组:

image

用map翻倍nums中的数字:

image

用filter过滤掉nums中的奇数:

image

是不是觉得很简单?

那么我们如何使用reduce实现相同的效果呢?

也很简单!

少侠请看~

使用reduce翻倍nums里面数字:

image

使用reduce过滤nums中的奇数:

image

怎么样!很简单吧?

翻倍数字了吧?

过滤出奇数了吧?

到这里,少侠你心里肯定在想:

image

哈哈,少侠你先别激动!

虽然上面两个例子是有点过分~

但是!

(这里请自动切换成严肃脸~?)

通过上面2个例子,我们至少明白了一件事,

那就是reduce是能够给我们想要的结果的,

它既可以像map那样,对一些元素执行操作,然后给我们一个相同长度的数组;

也可以像filter一样,给我们一个过滤掉某些元素后的比较短的数组;

或者其他一些奇奇怪怪的东西~

那么,

接下来我们的问题就是,

如何让reduce返回给我们想要的东西呢?

这里少侠你可能有2种情况,

第一种就是,你已经知道了你想要的结果,然后你直接通过reduce最后返回这个结果,也就是上面两个例子。。。

换句话说,reduce实际上啥也没做,只不过进去兜了一圈。。。

“reduce老弟,天辰那家伙又来翻倍nums数组了,上次是什么结果你还记得不?”

“记得,是 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]”

“好,直接扔给它,我们出去玩去~”

“嗯,好~”

image

当然,如果少侠你没有我天辰这么优秀~

你很可能没办法在一开始就知道具体的结果是什么,

这个时候,你就得自己告诉reduce如何生成你想要的元素了,

比如这样:

image

换个简单些的写法,同时把reduce里面的函数放到外面来:

image

好了,少侠~

我们已经初步实现了map的效果,那么接下来就应该是filter了,

一样的思路:

image

现在filter也有了,

我们把两种reducer结合起来使用一遍:

image

完全OK~

到这里,有的少侠可能就要说了:

“住手!天辰,你这样的话,你不是又要遍历2次数组,上次装逼时怎么说的你自己都忘了?!”

好吧,少侠,你还算是一个比较细心的人,

这里我们用了两次reduce, 所以确实会遍历2次数组,

但是~

谁说我就一定得用2次reduce了?

看好了,

少侠~

接下来我要开始装逼了,

基础内力不深厚的少侠请主动退后10米站远一些!

首先,

我们已经把mapReducer里面的翻倍操作提取出来了,

也就是我们熟悉的double函数,

现在,我们试着把mapReducer里面的向数组添加值的这个操作,

也单独提取出来:

image

然后,按照我们上一章说的,

mapReducer现在会严重依赖当前作用域中的double函数和pushValue函数,

所以,我们给它换种方式,换成通过传参的形式获取:

image

注意,少侠~

这里看着可能稍微复杂了一些,

但是所有我们做的,

实际上就只是把原先直接通过作用域访问的函数,

换成了依次通过函数参数传递访问而已,

把函数改成通过参数传递之后,

我们每次就可以自由选择传递什么函数进去,

比如,把double函数换成add1:

image

根据这个思路,

改变后的filterReducer会是这样:

image

到这里,如果少侠你有点懵逼的话。。。

别急,

待会儿你可能会更懵逼的!

以后有机会我们会回头单独分析里面的知识点的。。。

这里的重点是,现在我们可以更灵活的使用reduce了:

image

我知道你们想说什么~

现在还是用了2次reduce。。。

少侠你看,我现在在最后传递的是pushValue作为joinFn函数,

也就是说,过滤出奇数后,就添加到数组当中,

但是,我也可以,在添加到数组当中之前,不马上添加到数组中,

我们先翻倍一下过滤出的奇数,

完了过后再添加到数组当中~

image

现在只有一次reduce了!

然后,

不知道少侠你有没有注意到,

magic函数实际上可以用mapReducer函数实现

(请仔细认真观察~)

image

替换掉magic:

image

好了,

装逼结束~

哈哈哈哈哈哈!

“喂,天辰!你在这儿吹什么牛逼呢,你是不是忘了什么东西?说好的transduce呢!!!”

哦,差点忘了。。。

好吧,少侠,

transduce就是对下面这部分代码的进一步抽象:

image

但是,

老实说,

解释transduce比我想象的还要麻烦。。。

(早知道就该不选这个东西。。。。)

首先,

transduce通常需要一个compose函数配合使用:

image

有了compose函数,我们就可以简化下面的代码:

image

然后,

transduce大概长这个样子:

image

里面的参数分别对应下面几个部分:

image

其实就是把开始的几个部分拆分了开来,

这是它的使用方式,

image

把所有代码结合起来:

image

如果我们想增加一条过滤条件:

image

或者如果我们最后不是想获得数组,

而是给数组里面的数字求和的话:

image

好了,

恭喜你,少侠!

你又成功发现并阅读完了一篇文章~

按照惯例,首先~

谢谢少侠你看到了这里,

然后~

有的少侠可能会对这篇文章觉得比较懵逼,

这很正常,

一是少侠我可能写得也不是很清楚,

还有就是transduce的实现确实涉及到了很多其他的知识,

一大堆高阶函数,函数闭包,偏函数应用,以及函数组合compose等,

那么我为什么要把transduce分享给大家呢?

因为,

transduce本身也许并不是很重要,

少侠你完全可以不使用它,

但是,理解和掌握它所需的知识,对很多少侠来说都很重要,

特别是对想追求卓越,当一个dreamer的少侠~

还有就是。。。

如果少侠你平时对高阶函数,闭包,this关键字这些东西都比较懵逼的话,

比较抗拒的话~

那么,先看看更懵逼的东西,

等回过头再来看它们,

你会觉得它们亲切多了~

所以~

少侠,

你到底懵逼了没?


一些你可能关心的问题:

1、天辰,你老实说!你写这篇文章是不是就是想装逼?

少侠,装逼能帮我吸引到妹子不?

如果能,那我就是在装逼,

如果不能,那我就是在分享技术文章。。。

2、天辰,这次你弄了个感觉没什么用的transduce,下次又打算弄什么东西来?

这次不能随便立flag了,

弄个transduce差点把我坑死。。。

不过,

下次可能会遇见下面几种情况之一,

遇见一个新的道具,比如上面遇见的compose函数:

image

遇见新的秘籍或残卷,关于函数,对象,递归什么的:

image

遇见一个冒险挑战,完成某个特殊的挑战:

image

3、天辰,你说transduce设计到了很多关键知识点。。。

image

哈哈哈哈哈~

image


其他资源:

文章:

Transducers: Efficient Data Processing Pipelines in JavaScript

Understanding Transducers in JavaScript

工具库:

ramda库中的transduce

transducer.js


好了,

少侠,江湖路上,有缘再见~

image