00:00
了解了reduce,那接下来呢,我们再来了解一下另外一种进行规约和聚合的高级函数,那就是fold折叠。fold和reduce呢,整体来看。其实是非常的类似,可以认为fold是reduce的一种扩展,它们俩其实是非常接近的啊,那具体来使用的过程当中有什么区别呢?我们看一下直接调用的结果是什么样的,List我们可以直接扣函数,我们看一下它的底层实现,里边我们是要传两个参数的。这里传两个参数,一个是这个叫做Z,然后另外一个叫o po po我们比较熟悉,这跟reduce一样,这不就是要传的那个聚合的操作吗?呃,而且这个跟reduce也一样啊,就是当前的。第一个数哎,表示我们当前的一个聚合的状态,然后第二个呢,就是当前新进来的一个元素,那最后得到的数据类型呢,是新的聚合之后的状态,它们都是同样的数据类型,而这里边又有一个ZZ表示什么呢?
01:09
它其实表示的是一个聚合的初始状态,我们可以点到源码里边仔细看一下啊,Forld的底层调用的是for the left for the left,我们看一下,哎,这里边是一个笔画的这种表示啊,传两个参数进来,一个Z,一个op,然后接下来我们看到在里边呢,呃,它定义的这个op聚合的状态B和当前的。数据元素的类型A可以不同啊,每次聚合的结果聚合状态还是B啊,这个是可以拆开的,然后我们接下来看一下里边定义了什么东西,它定义单独定义了一个object。叫做folder的一个object。那我们看到它其实是一个function,它其实是一个函数,对吧,那我们来看一下里边它定义了一个属性叫做result。它的值就是Z,而且它是一个变量,所以它接下来要改变的里边呢,Over rightde,它的object方法,所以我们知道这个object,我们可能后边会直接使用,就是直接用这个folder啊,然后相当于是调它的apply方法,Apply方法呢要传一个V1作为参数。
02:20
我们看他干了一件什么事,他其实就是调用了我们当前的这个op操作,我们的聚合操作,把result和V1做一个聚合,然后呢,得到的结果又给到了result。那家看这个操作是干了件什么事,这不就是result,就是我们当前的聚合状态吗?聚合状态,然后之前的聚合状态,然后新来一个数,再做一个聚合,得到结果呢?更新聚合状态,不停的聚合,不停的更新,而result的初始值就是Z,所以Z就是一个初始聚合状态。后面调用的时候也非常的有趣,我们看到这里就是this空格,那大家知道这种调用方式其实就是点的那个省略嘛,省略了点的内容方法调用啊this.for each,那不就是把当前的集合类型要做一个便利里边的每一个元素,诶后面这是for each的参数,是一个方法,一个函数,那这个函数干了一件什么事呢?显然就是要调apply这里边的这个操作了,我们里边要干的就是对于每一个元素都执行一下。
03:33
当前的这个元素不就是V1吗?哎,那所以都执行一下跟之前状态result的聚合,得到结果,最后result返回,这就是foot left具体的一个操作的过程,所以刚才我们就知道了,第一个参数传进来的就是初始聚合状态,那比方说我们直接给一个给一个十,那然后比方说啊,后面我们还是基于一开始的这个乘法,直接做一个加的操作。
04:09
下划线做一个。直线,然后直接把它打印出来,我们可以看到到结果就变成了20。啊,那所以它的结果当然是对应着我们前面一加二加三加四加,呃,起来还十,那再有一个初始值的话,就变成了20,我们完整的把这个过程解列局写在后边,就是算的过程,啊,那大家自然想到了对应的这个fo left跟fo肯定是一样的嘛,那我们再来测试一下,如果要是减法的话,会是一个什么样,是一个什么效果。下划线减下划线很好想,那不就变成了值作为初始值,后边每来一个数在后边做聚合,那就是十减一减二减三。
05:08
减四就是这样一个操作吗?应该得到零了,我们看一看是不是这样。没有问题,200,那除了for和for the left之外,咱想到了有没有for the right呢?我们直接看一眼啊,那for right,为了方便跟之前做对比,我们还是用这个LIST2来做一个说明。LIST2直接掉forld right,我们点进去就会看到for right同样也是两个参数,那这个Z我们想到了,肯定也是一个初始值了,Op啊,那这个当然也是一个对应的聚合操作了。这里边比较。大家需要注意的一点是,Op这里边的这个操作,其实A是我们当前输入的一个新的数据,而B呢,其实是聚合的状态,大家看到底层啊,它是掉了一个什么,是一个reverse,然后点for the left,所以它底层掉的还是for the left。
06:09
只不过呢,是先做了一个翻转。啊,就是reverse,我们知道当前list如果调这个reverse的话,不就是完整的先把它翻过来吗?翻个个,然后再fold left,从左到右开始依次聚合,那大家知道翻之前那不就相当于是从右到左依次聚合吗?哎,那关键是你要注意它前后的这个数据啊,它的这个聚合的顺序是什么样的,Z这个初始值是不变的,然后呢,关键看它后边的这个操作改成了把当前的这个further left的操作改成了right left。当前的参数,第一个参数for the left第一个参数是我们的。聚合的状态嘛,然后第二个参数是每一次新添加进来的数据,这个比较好理解,为什么它叫做right和left呢?对应在我们原始的这个数据里边的话,我们现在翻转之后,其实是要从右往左聚合,所以聚合的状态应该其实是之前的right。
07:14
那新来的数据呢,其实是left,其实是在左边的,从原始的例子。列表来看的话,那应该是在左边啊,这个就是要结合我们的具体数据来考察,那繁入对应的这两个数来之后做了什么操作呢?直接调用了op的操作,传进来的是left和right,哎,所以这里边调这个op操作的时候,还是left在前,Right在后,比方说现在我们的op是减,那就还是左减右。哎,所以大家要注意啊,现在的这个操作,比方说我们还是直接给一个初值,这个给个11吧,后边来一个下划线减下划线一个减法操作,当前如果要我们完整的写出来的话,应该是什么样子呢?哎,首先我们把这个肯定都是减啊。
08:08
前面是三,然后减四减五,减八减十,肯定是整体的,这个顺序都是这样的,结合顺序我们要注意了,首先是做了翻转,而且翻转之后呢,初始值还是11,这里有11 11是作为我们当前调用时候的。家想到的状态是在右边对吧?哎,所以是在最右边,这是我们的初始状态,然后呢,具体操作的时候是左减右,所以大家知道了,第一个操作应该是十减之一,这是我们当前的第一次操作。然后接下来第二步操作,那就是八减十减11的结果,那后边五减。
09:00
八减十减11的结果,后面再加一个括号四再减去它,最后用三减去它,哎,所以目前如果要是跟之前的bos right做一个对比的话,也就是多加了一个初始值,只不过这里的初始值呢,是要放在我们最右边的,也就是最后一个数的后边,然后它的操作顺序还是。最后一个数去放在前边去减去我们的初始值,它是这样一个顺序。这个大家需要稍微的注意一下,那计算的话,我们就看到了这个一减负一八减去一正九五减正九负四,得到四减负483减八应该是。得到的结果是,不,我们运行一下,看看是不是符合预期。看到没有问题,这就是for right的一个写法,我们结合源码给大家做了详细的介绍,那总结起来的话,其实也就一句话啊,Reduce和fold都是要把我们当前的一个集合,根据传进来的某一个操作,要做一个规约聚合,最后聚合到一个值,而对于这个reduce而言,它是没有初值的,或者大家认为初值就是第一个数,而对于负而言呢,它是要单独的传入一个初值,然后跟集合里边的所有元素去做这样的一个结合,啊,这就是我们这里边不同的一点。
10:36
关于高级计算函数里边的规约,Reduce类的操作,我们就讲到这里。
我来说两句