你好,我是小必,感谢与你在这里相遇。

今日内容:循环递归函数List.Accumulate函数。


在Power Query中,List.Accumulate函数是一个高阶函数,同时也是一个很重要的函数。学习List.Accumultae函数,说明你的Power Query的M语言已经进入到了一个比较深的阶段了。这个函数是也是M语言中高难度的函数之一,但是很有用。


由于M是函数语言,这个里面是没有循环类的语言,如VBA中的for语句,或者do loop之类的。所以这个函数的功能也很简单,就是循环。


先来看一下官方给出的函数的解释与语法。从下面的这个语法说明中,着实没有看明白这个函数是干什么用的。



简单来说,这个函数的语法,可以写个如下:


List.Accumulate( 迭代运算参考列表, 迭代初始值, 根据迭代运算参考列表进行迭代运算 )


第一个参数迭代运算参考列表的类型是一个List;第二个迭代的初始值可以是list,record,文本,table等等;第三个参数就是迭代运算部分。


案例1

先看一下简单的例子:求1到9的累计的和。

= List.Accumulate({1..9},0,(x,y)=>x+y)

此时的公式可以写成这样:List.Accululate是需要自定义的,对于循环来说,需要先定一个容器用来放结果,还需要相应的循环变量,那么就List.Accumulate的第二个参数,这个公式中定的循环是一个数字,初始值为0,(x,y)=>这一部分中的x,y是指代的变量,即x为第二个参数,y为第一个参数中的每个元素。来看一下循环:


初始值为第二个参数即0,循环运算为将迭代的参考值与进行累加。


第1次循环:初始值为0,即x=0,y={1..9}{0}的第一个元素,即为1,所以x+y=1;

第2次循环:初始值为上一次循环中执行的x+y=1,即x=1,y={1..9}{}1的第二个元素,即为2,所以x=y=1+2=3;

……

最后一次循环,初始值为x=0+1+2+3+4+5+6+7+8=36,y={1..9}{8}的第9个元素,即为9,所以x+y=36+9=45.

最终返回的结果为45.



案例2

上面的例子只是返回一个累加的数字,所以难度再提升一下:计算{1..9}的累加合计,返回一个与list同样尺寸的list。

先看一下代码:

= List.Accumulate({1..9},{},(x,y)=>x&{List.Sum({List.Last(x),y})})


相比较上面的入门的例子,这个例子就相对来说比较复杂了。首先定一个容器,即为一个list,且为空list,如{},即没有任何一个元素。List.Last是返回一个列表中的最后一个元素,List.Sum是对列表进行求和。


这个里面{List.Last(x),y}List.Last返回的是一个元素,即数值,y也是{1..9}中的数值,而此时的x是一个列表,即{},所以在合并的时候对于List.Last(x)与y外面套一个{}组成一个列表,而使用List.Sum求和后仍然是一个元素,还需要转化成列表,加一个{}即可。


第1次循环:初始值为{},即x={},y={1..9}{0}的第1个元素,即y=1.此时x&{List.Sum({List.Last(x),y})}={}&{1},即{1}。


第2次循环:初始值为{1},即x={1},y={1..9}{1}的第2个元素,即y=2.此时x&{List.Sum({List.Last(x),y})}={1}&{3},即{1,3}。


第3次循环:初始值为{1,3},即x={1,3},y={1..9}{2}的第3个元素,即y=3.此时x&{List.Sum({List.Last(x),y})}={1,3}&{6},即{1,3,6}。

……

最后1次循环:初始值为{1,3,6,10,15,21,28,36},即x={1,3,6,10,15,21,28,36},y={1..9}{8}的第9个元素,即y=9.此时x&{List.Sum({List.Last(x),y})}={1,3,6,10,15,21,28,36}&{45},即{1,3,6,10,15,21,28,36,45}。


拓展

需要注意的是这个函数的第3个参数是(x,y)=>是固定的写法,x与y可以替换成任意的变量。


为了方便大家与VBA中的循环语句进行对比,现贴出VBA代码,以便用来对比学习。



Sub 累加() Dim i As Integer i = 2 Do While Cells(i, 1) <> "" s = s + Cells(i, 1) Cells(i, 2) = s i = i + 1 Loop End Sub


Sub l累加2() Dim i As Integer i = 2 Do If Cells(i, 1) = "" Then Exit Sub Else s = s + Cells(i, 1) Cells(i, 2) = s End If i = i + 1 Loop End Sub


Sub 累加3() Dim i As Integer i = 2 Do Until Cells(i, 1) = "" s = s + Cells(i, 1) Cells(i, 2) = s i = i + 1 Loop End Sub