list循环_Power Query笔记——循环,迭代,递归

5e7fb7ccb36d05ccd317a8b0ee9aa532.png

2018-04-13学习笔记:

捋一捋Power Query里面的循环,迭代和递归


循环

在Power Query中循环是Transform类函数,如列表循环:List.Transform;

表循环函数:Table.TransformColumns;记录循环:Record.TransformFields。

循环就是将容器中的元素一个一个的拿出来,依次进行操作,例如我们构建一个{1,2,3}的列表,现在需要将列表中的每个元素都进行*10的运算,如下图

88b225403137929b1eb20d366e36d27a.png

代码:= List.Transform({1,2,3}, each _*10)

使用列表循环函数List.Transform,该函数的意思就是将列表{1,2,3}中的每个元素依次循环出来,赋予给后面的下划线,列表有几个元素,该函数就进行几次操作

第一次:循环出列表中的1,赋予给后面的下划线,然后*10,得到10
第二次:循环出列表中的2,赋予给后面的下划线,然后*10,得到20
第三次:循环出列表中的3,赋予给后面的下划线,然后*10,得到30
最终返回得到的新列表{10,20,30}。

循环函数最终得到的元素个数和初始列表的个数一致。


迭代

重复执行一系列运算步骤,从前面的量依次求出后面的量的过程,此过程的每一次结果,都是由对前一次所得结果施行相同的运算步骤得到的。简单的迭代就是累计求和,

Power Query的List.Accumulate就属于迭代函数

6f65dbc02492b12461a43fc3a8ae7257.png

参数一:为需要求和的列表{1,2,3,4,5}

参数二:提供一个初始值0

参数三:有两个变量,x等于每次迭代之后的值,y等于列表中的元素

该函数的运算规律如下:

第一次:x等于我们指定的初始值0,y=1,计算 x+y=> 0+1=1;
第二次:x等于上一次计算的结果1,y=2,计算 x+y=> 1+2=3;
第三次:x等于上一次计算的结果3,y=3,计算 x+y=> 3+3=6;
第四次:x等于上一次计算的结果6,y=4,计算 x+y=> 6+4=10;

List.Accumulate返回最后一次计算的结果,迭代是一种累计循环,最后只有一个值。

这好像看不出有什么厉害,这求和直接List.Sum不就可以了么?在来看一个复杂的例子

需要将列表{1..10}中偶数和奇数分别放在两个列表中,如下图:

08f94c9004a25097cd43774ae718dd75.png

代码:

= List.Accumulate({1..10}, {{},{}},

(x,y)=> if Number.IsEven(y) then {x{0}&{y}, x{1}} else {x{0}, x{1}&{y}})

Number.IsEven判断值是否是偶数
x{0} 深化x中的第一个元素,x{1}&{y}

来分析一下这段代码的运算逻辑,

还的分步骤:

第一次:x等于我们指定的列表 x={{}, {}} , y=1
判断 Number.IsEven(1)=False,
则执行else后面的代码,{x{0}, x{1}&{y}}
x{0} 深化x中的第一个元素 = {}
x{1}&{y} 深化x中的第二个元素在链接{y} => {}&{1}={1}
最终运算的结果为{x{0}, x{1}&{y}} = {{}, {1}}
第二次:x等于第一次运算的结果 x={{}, {1}},y=2
判断 Number.IsEven(2)=True,
则执行then后面的代码,{x{0}&{y}, x{1}}
x{0}&{y} 深化x中的第一个元素在链接{y} => {}&{2}={2}
x{1} 深化x中的第二个元素 = {1}
最终运算的结果为{x{0}&{y}, x{1}} = {{2}, {1}}
第三次:x等于第二次运算的结果 x={{2}, {1}} , y=3
判断 Number.IsEven(3)=False,
则执行else后面的代码,{x{0}, x{1}&{y}}
x{0} 深化x中的第一个元素 = {2}
x{1}&{y} 深化x中的第二个元素在链接{y} => {1}&{3}={1,3}
最终运算的结果为{x{0}, x{1}&{y}} = {{2}, {1,3}}
第四次:x等于第三次运算的结果 x={{2}, {1,3}},y=4
判断 Number.IsEven(4)=True,
则执行then后面的代码,{x{0}&{y}, x{1}}
x{0}&{y} 深化x中的第一个元素在链接{y} => {2}&{4}={2,4}
x{1} 深化x中的第二个元素 = {1,3}
最终运算的结果为{x{0}&{y}, x{1}} = {{2,4}, {1,3}}
第五次:x等于第二次运算的结果 x={{2,4}, {1,3}} , y=5
判断 Number.IsEven(5)=False,
则执行else后面的代码,{x{0}, x{1}&{y}}
x{0} 深化x中的第一个元素 = {2,4}
x{1}&{y} 深化x中的第二个元素在链接{y} => {1,3}&{5}={1,3,5}
最终运算的结果为{x{0}, x{1}&{y}} = {{2,4}, {1,3,5}} ......

重点就是x,每次进行计算的时候,x都等于上一次运算的结果。


递归

程序调用自身的编程技巧称为递归,如果一个函数在内部调用自身本身,这个函数就是递归函数。

递归这个概念之前想了很久,没有深刻理解,今天在M群看到一个例题,突然就领悟了。其实递归和迭代很类似,先来看一个简单的递归,如下图:

9d79f228ce5651450aead19001c7bba2.png

会发现这个代码计算结果和上面List.Accumulacte的第一个案例相同,也就是求列表

{1,2,3,4}的和。

@是作用域操作符,引用函数在其范围内,简单来说就是允许函数再次调用本身,从而实现递归。

那么这个递归函数是如何进行计算的么:

给予的参数是x = 4 ,不满足 if 条件,则执行else后面的代码 fx(x-1)+x =>fx(3)+4,
第二次调用函数,x=3,不满足 if 条件,fx(2)+3+4
第三次调用函数,x=2,不满足 if 条件,fx(1)+2+3+4
第四次调用函数,x=1,满足条件,则执行 then后面的代码
最终 fx(4) => 1+2+3+4 =10

关于PQ里面的递归,可以参考施阳的博客,有详细的讲解(想当初看这篇文章的时候,头发掉了一大把)

递归函数 | Power Query爱好者​pqfans.com

循环+递归

有这样一个题,需要将下面列表中的所有元素*10

9f1d155663f15e2776ea975e6306edb2.png

所有元素*10,想到的就是循环函数List.Transform,然而会发现列表中嵌套有列表,当循环到列表元素的时候,无法进行计算。

c88193b8de142951edafff6ff5e838dd.png

我们需要继续使用List.Transform函数对子列表中进行循环,这里就可以使用递归

320e77feefc972ba916c9ac2f3c5c76a.png
let
    list = {1,2,{3,4,{5,6}},{7,8},9},

    fx = (x)=> List.Transform(x, each 
                   if _ is number 
                   then _*10 
                   else @fx(_)
                    )
in
    fx(list)

定义一个递归函数fx(x),循环参数x里面的每一个元素,判断如果元素为数值,则进行*10的运算,如果不是,则用该元素作为参数进入第二次循环 @fx(_)。


迭代+递归

还是上面的例题,现在需要将列表 list = {1,2,{3,4,{5,6}},{7,8},9} 进行求和,同样有嵌套的情况,无法使用List.Sum。

使用迭代+递归的方法来完成,最终结果

6d5f99d2c5172bd1d1722a7330a1060c.png
let
    list = {1,2,{3,4,{5,6}},{7,8},9},

    fx = (x)=> List.Accumulate(x,0,(x,y)=> 
                   if y is number 
                   then x+y 
                   else x+@fx(y)
                    )
in
    fx(list)

1+2+3+4+5+6+7+8+9=45

和循环的逻辑一样,依次判断列表中的每个元素,如果是数字则进行累计,如果不是那么进入第二次迭代计算,并与前面的累计结果相加。

当然还有其他方法可以进行求和计算,这里只是为了学习递归,


秃头......

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值