2024/11/7:とりあえずパターンで覚えるLET&LAMBDA再帰式 〜自由に指定できるループを数式で〜
≪毎週木曜12:15~ZOOMで開催中!Excel関数お勉強会の内容です。》
◇LET&LAMBDA再帰によるループ式
■ 覚える(使えるようになる)メリット
ループ処理内で使える引数を何個でも設定できる
条件指定でのループ終了を指定できる
REDUCE関数などを使ったループだと、引数が「initial_value」と「array」の2つしかなく、処理に使える引数となると実質1つしかないようなもの。
その点、LAMBDA関数自体にはそんなに引数の数の制限はないので(最大 253 個らしい by MS公式)、割とやりたい放題できる。
また、「対象がなかったら終了させる」「""だったら終了させる」というような”条件”でループを終了させる事ができるので、条件を満たすまで何度でもループしてくれるのも大きい。(※負荷等による上限はさておき。)
処理回数を指定するタイプのREDUCEループだと、第2引数の配列の上から下まで(1ターン)いったら終わり、もしくは無理やり何ターンか回すことも出来るけど、結局はループ回数を指定しなきゃならないので大きな数字で一旦無駄な処理をさせないといけなかったり、LAMBDA式の入れ子になって、むしろそっちの方がややこしい式になりがち…。
■ 基本パターンのベース式
PCの辞書登録でも何にでもして、好きに使うがいいよ!ヾ(・ω・)ノ
▼メイン部分
=LET(_r,LAMBDA(_r,【第1名】,【第2名】,IF(●)),_r(_r,【第1初期値】,【第2初期値】))
▼IFの ● の部分
【終了条件】,【終了時処理】,_r(_r,【第1用処理】,【第2用処理】)
【第1名】…「第1引数」の名前をきめて入れる
【第2名】…「第2引数」の名前をきめて入れる
【第1初期値】…ループ開始時点の「第1引数」の初期値を入れる
【第2初期値】…ループ開始時点の「第2引数」の初期値を入れる
【終了条件】…どうなったときにループが終わるかを指定する
【終了時処理】…終了条件を満たした場合、どういう処理をするのか?(または何を表示させるのか)を指定する
【第1用処理】…終了条件を満たさなかった場合、第1引数の値(or配列)をどういう風に変化させて次へループさせるかを指定する
【第2用処理】…終了条件を満たさなかった場合、第2引数の値(or配列)をどういう風に変化させて次へループさせるかを指定する
※ 例では引数は2つだけど、3つでも4つでも必要なだけ増やしてOK。
※ 終了条件なくExcel再帰式は成り立ちません。
Excelの関数式は、”答えが出ない”式は良くも悪くもエラーになります。
ループし続ける状態(深く潜り続ける状態)では答えがでないので、
「何回ループしたら終わり」だとか「エラーだったら終了」だとか、
終了させる条件を入れる必要があります。
■ LET&LAMBDA再帰式の具体例({1;2;4;8;…512;1024} 配列)
▼ループさせる回数を指定するパターン例
=LET(_r,LAMBDA(_r,arr,cnt,
IF(cnt=10,
arr,
_r(_r,VSTACK(arr,TAKE(arr,-1)*2),cnt+1))),
_r(_r,1,0))
配列(arr)の初期値を「1」、カウント(cnt)の初期値を「0」で開始、
配列と配列の一番下の数値を2倍にしたものをVSTACKで連結したものを、
次のループの配列(arr)として処理させる。
それを10回分ループさせて、最終的にできあがった配列(arr)を出力。
▼終了条件を指定するパターン例①
=LET(_r,LAMBDA(_r,arr,next,
IF(next>1000,
VSTACK(arr,next),
_r(_r,VSTACK(arr,next),next*2))),
_r(_r,1,1*2))
配列(arr)の初期値を「1」、下に連結させる次の相手となる次の値(next)の初期値を「1*2」で開始。
配列(arr)は次の値(next)と連結、次のループの配列(arr)として処理させ、nextの値を2倍したのを次のループの次の値(next)として処理。
連結させる次の値(next)が1,000を超える場合、連結させたものを出力。
超えない場合はループ処理を続ける。
※初期値の時点で、手動というか脳内計算とかいれちゃってるw
次の値が簡単にわかるような処理内容なら、こういう書き方でも
別にいいとは思う(ただし格好よくはない…)
▼終了条件を指定するパターン例②
=LET(_r,LAMBDA(_r,arr,
IF(@TAKE(arr,-1)>1000,
arr,
_r(_r,VSTACK(arr,@TAKE(arr,-1)*2)))),
_r(_r,1))
初期値は、配列(arr)の「1」のみで開始。
配列(arr)と”配列の一番下の数字”に2をかけたものをVSTACKで連結。
”配列の一番下の数字”が1,000を超えていたら、現時点の配列(arr)を出力。
超えない場合はループ処理を続ける。
※TAKE関数の前に”@”をつけているのは配列処理の関係で、ちゃんと
配列ではなく単体の「値」として扱わないと、第2引数と第3引数が
多い方の配列枠数に引きずられて、配列枠が自動拡張された状態で
次のループに進んでしまい、不要なNAデータが付いてしまうからです。
(この式の場合、@1つ分につき1枠分、毎ループ毎に拡張される状態)
※ちなみに、何重かでNAエラーのデータが出るような状態になると
#NUM!エラーになる事もあります。
(↑の式の場合2つとも@を消すと確認できる)
◇あとがき
ま、とりあえず。
何となくでも使い方が分かったら、使ってみてくださいなヾ(・ω・)ノ
「終了条件を指定するパターン例②」の@つける付けないに関しては、
直接LAMBDA式には関係ないというか メインは配列の動き的な部分ですが、
ループさせていることで結果的に大きな影響が出てしまう部分・・・。
配列やIFの動きについては、過去の勉強会ではやったけどもその頃はまだ
noteも初めてなかったし、勉強会は毎回同じ人が来れている訳ではないので
またそのうち、改めて「配列の動き」回や「IF関数」回やりましょかね。
次回は、『仕組みを理解しないと覚えられない私みたいな面倒くさい人向けのLET&LAMBDA再帰式解説』予定
…ではあるんだけど、うまく出来るかな💦…というか時間足りるのか?💦