日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

for each循环_Power Query — 循环初步

發(fā)布時(shí)間:2025/3/11 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 for each循环_Power Query — 循环初步 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題記:

《Excel圣經(jīng)》1:3 微軟說(shuō),“要有循環(huán)”,便有了循環(huán)。


引子:

keyword: one of and as each else error false if in is let meta not otherwise or section shared then true try type #binary #date #datetime #datetimezone #duration #infinity #nan #sections #shared #table #time

可以發(fā)現(xiàn)M語(yǔ)言的關(guān)鍵字里面并沒(méi)有for/while這樣的關(guān)鍵字,那么M如何實(shí)現(xiàn)循環(huán)呢?


遍歷:

M實(shí)現(xiàn)循環(huán)是通過(guò)特定的函數(shù)或者運(yùn)算符來(lái)實(shí)現(xiàn)的,按照實(shí)現(xiàn)原理的不同,可以初步地分為——遍歷、迭代與遞歸三大類,我們先看一些簡(jiǎn)單的遍歷案例:

~~~~~~~~~~

案例1:不使用Repeat函數(shù),生成一個(gè)list,里面有20個(gè)Number "1"。

~~~~~~~~~~

在M語(yǔ)言中,就有一個(gè)函數(shù)可以遍歷一個(gè)list,它就是List.Transform ——

List.Transform(list as list, transform as function) as list

這個(gè)函數(shù)實(shí)現(xiàn)的功能其實(shí)是“l(fā)ist內(nèi)元素轉(zhuǎn)化”的功能,但由于這個(gè)過(guò)程會(huì)遍歷list中的每一個(gè)元素,因此我們可以把這個(gè)函數(shù)當(dāng)做for循環(huán)來(lái)使用:

= List.Transform({1..20},(x)=>1)

我們?cè)倏纯催@個(gè)實(shí)現(xiàn)過(guò)程:將構(gòu)造的{1..20}的每一個(gè)元素都轉(zhuǎn)化為1,構(gòu)造了1~20共20個(gè)元素的序列,因此最終轉(zhuǎn)化的結(jié)果也是有20個(gè)數(shù)字1的list。

~~~~~~~~~~

案例2:使用List.Transform函數(shù),生成20以內(nèi)的全部奇數(shù)。

(List.Numbers可以快捷實(shí)現(xiàn),本節(jié)重點(diǎn)介紹的是循環(huán),因此不使用)

~~~~~~~~~~

我們知道全體奇數(shù)可以通過(guò)自然數(shù)來(lái)構(gòu)造,因此我們?nèi)菀紫氲?#xff1a;

= List.Transform({1..10},(x)=>2*x-1)

我們回顧下實(shí)現(xiàn)過(guò)程,20以內(nèi)最大的奇數(shù)是19,而19=2*10-1,因此我們需要構(gòu)造{1..10}這樣的list來(lái)進(jìn)行遍歷,通項(xiàng)公式就是(x)=2*x-1。

~~~~~~~~~~

案例3:使用質(zhì)數(shù)的定義證明19是質(zhì)數(shù)。

~~~~~~~~~~

質(zhì)數(shù)定義:在大于1的自然數(shù)中,除了1和它本身以外不再有其它的因數(shù)。

所謂因數(shù)就是能夠整除給定的數(shù),我們可以通過(guò)Mod函數(shù)來(lái)判斷,只要余數(shù)為0,那就是因數(shù),因此我按照定義把2~18全部逐一驗(yàn)證遍即可:

= List.Min(List.Transform({2..18},(x)=>Number.Mod(19,x)))

上述表達(dá)式結(jié)果為1,說(shuō)明2~18分別除19得到的余數(shù)list中最小值為1,沒(méi)有0,也就是19除了1和自身外不再有其它的因數(shù)了,因此19為質(zhì)數(shù)。


迭代:

我們先考察一個(gè)簡(jiǎn)單的計(jì)數(shù)問(wèn)題:10以內(nèi)偶數(shù)的個(gè)數(shù)是多少?

顯然使用List.Count是無(wú)法得到結(jié)果的,最簡(jiǎn)單的思路就是我們假設(shè)有一個(gè)容器專門用來(lái)實(shí)現(xiàn)計(jì)數(shù)的功能,逐一判斷10以內(nèi)的每一個(gè)自然數(shù)是不是偶數(shù),如果是偶數(shù),計(jì)數(shù)器就加一。那么對(duì)于計(jì)數(shù)器的上一個(gè)結(jié)果來(lái)說(shuō),每次新出現(xiàn)一個(gè)偶數(shù),計(jì)數(shù)器的結(jié)果就“迭代”更新了一次。

上述解決問(wèn)題的過(guò)程就是接下來(lái)要介紹的迭代循環(huán)了。

~~~~~~~~~~

案例4:10以內(nèi)的奇數(shù)有多少個(gè)?

~~~~~~~~~~

在M中,Accumulate函數(shù)具有積累的功能,可以實(shí)現(xiàn)“容器”迭代的功能,我們通過(guò)Number.IsOdd函數(shù)來(lái)對(duì)每一個(gè)數(shù)做是否為奇數(shù)的判斷:

List.Accumulate(list as list, seed as any, accumulator as function) as any

這個(gè)函數(shù)需要給定一個(gè)種子參數(shù)作為起始值,然后根據(jù)指定的function進(jìn)行迭代運(yùn)算。

= List.Accumulate({1..10},0,(x,y)=>if Number.IsOdd(y) then x+1 else x)

我們回顧下迭代的過(guò)程:

首先計(jì)數(shù)器(seed)的初始值為0,然后開始對(duì){1..10}依次做判斷,(x,y)的x就是上一次的seed,而y就是當(dāng)前{1..10}的一個(gè)值;最初x為0,y為1,然后y依次為2~10,x對(duì)應(yīng)的為上一次function運(yùn)算結(jié)束后的那個(gè)值;因此1判斷為奇數(shù)時(shí)x就執(zhí)行了then x+1(這里面的x還是seed的值:0),因此當(dāng)對(duì)y=2做判斷時(shí),就執(zhí)行了else x,x值不變,當(dāng)全部判斷完時(shí),輸出x最后的值,也就是5,這樣就完成了整個(gè)迭代循環(huán)。

~~~~~~~~~~

案例5:使用迭代循環(huán)的方法倒序輸出“Hello World!”。

~~~~~~~~~~

既然要求使用迭代,那么就要想清楚“容器”里面到底裝什么內(nèi)容,這個(gè)例子需要倒序輸出,我們不妨將最終輸出的結(jié)果理解為一個(gè)一個(gè)字符拼接成的字符串,這樣我們就知道怎么構(gòu)造這個(gè)字符串容器了:

= List.Accumulate({0..(Text.Length("Hello World!")-1)},"",(x,y)=>

x&Text.At("Hello World!",Text.Length("Hello World!")-y-1))

這里使用了一個(gè)小技巧,使用了N-x的結(jié)構(gòu)構(gòu)造一個(gè)降序的list,實(shí)現(xiàn)順序迭代時(shí)是從后向前進(jìn)行的,然后使用字符串容器保存這些迭代的字符串,最終輸出。


遞歸:

前面介紹過(guò)@這個(gè)符號(hào),它的作用是調(diào)用后面的內(nèi)容,后面接函數(shù)時(shí),就是遞歸了。

我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)看看遞歸的作用和用法:

~~~~~~~~~~

案例6:計(jì)算9!(不使用Number.Factorial)。

~~~~~~~~~~

let

factorial=(x)=>if x=1 then 1 else x*@factorial(x-1)

in

factorial(9)

我們把這個(gè)語(yǔ)句和高中學(xué)的數(shù)列對(duì)應(yīng)起來(lái)就好理解了,首先告知首項(xiàng)f(1)=1,然后使用遞歸的方法寫出遞推公式f(n)=n*f(n-1),最后求第9項(xiàng)。

不難發(fā)現(xiàn),遞歸具備如下幾個(gè)特點(diǎn):

1.函數(shù)調(diào)用了自身,并用“@”進(jìn)行函數(shù)名的標(biāo)識(shí);

2.調(diào)用自身時(shí),參數(shù)會(huì)發(fā)生變化,避免無(wú)限遞歸;

3.通過(guò) if 語(yǔ)句對(duì)特定參數(shù)的函數(shù)值進(jìn)行了定義。

~~~~~~~~~~

案例7:求36和63的最小公倍數(shù)。

~~~~~~~~~~

我們都知道兩個(gè)整數(shù)的最小公倍數(shù)等于兩數(shù)之積除以兩數(shù)的最大公約數(shù),因此這個(gè)案例如果能夠解決如何求最大公約數(shù),問(wèn)題也就迎刃而解了,下面先介紹一種比較高效的算法。

輾轉(zhuǎn)相除法:

用較小數(shù)除較大數(shù),再用出現(xiàn)的余數(shù)(第一余數(shù))去除除數(shù),再用出現(xiàn)的余數(shù)(第二余數(shù))去除第一余數(shù),如此反復(fù),直到最后余數(shù)是0為止,最后的除數(shù)就是這兩個(gè)數(shù)的最大公約數(shù)。

這里面核心遞歸的是什么步驟?這個(gè)一定要理清楚,否則就寫不出正確的遞歸語(yǔ)句。看完介紹后可以發(fā)現(xiàn),最核心的一步就是用余數(shù)去除除數(shù),如果不好理清余數(shù)除數(shù)的關(guān)系,你就這樣理解:用最小的那個(gè)數(shù)去除中間的數(shù)。(被除數(shù)最大,除數(shù)第二排中間,余數(shù)最小)

let

GCD=(x,y)=>if y=0 then x else @GCD(y,Number.Mod(x,y))

in

36*63/GCD(36,63)

我們用數(shù)列的遞推公式思路把這個(gè)案例的核心步驟理一理:

GCD(x,y)=GCD(y,Number.Mod(x,y))

用語(yǔ)言描述就是:大數(shù)和小數(shù)的最大公約數(shù)等于小數(shù)和兩數(shù)取余的最大公約數(shù)。


for循環(huán)和while循環(huán):

前面的遍歷基本上可以實(shí)現(xiàn)for循環(huán)的效果了,那么while循環(huán)與哪一個(gè)函數(shù)最接近呢?

這里介紹一個(gè)用得稍微少一點(diǎn)的循環(huán)函數(shù):

List.Generate(initial as function,condition as function,next as function, optional selector as nullable function) as list

~~~~~~~~~~

例如下面這段Python代碼:

#!/usr/bin/python3

i=0

while i<10:

i=i+1

print(i)

~~~~~~~~~~

使用M語(yǔ)句就是:

let

list=List.Generate(()=>1, each _ <11, each _ + 1)

in

list

這個(gè)函數(shù)的特點(diǎn)也是有初始值,然后有一個(gè)條件判斷,條件內(nèi)會(huì)一直循環(huán)下去。


下篇筆記:《循環(huán)嵌套與綜合應(yīng)用》

總結(jié)

以上是生活随笔為你收集整理的for each循环_Power Query — 循环初步的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。