美文网首页
少侠,你的transducer到了,请拿去装逼~

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

作者: 天辰dreamer | 来源:发表于2020-02-10 16:01 被阅读0次

    [图片上传失败...(image-dc4ef6-1581321611007)]

    少侠们好~

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

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

    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

    相关文章

      网友评论

          本文标题:少侠,你的transducer到了,请拿去装逼~

          本文链接:https://www.haomeiwen.com/subject/cuwaxhtx.html