LAMBDA以降の新関数の使用例
2022年2月頃以降にLAMBDA関数とそれに関係する多くの関数が365で順次リリースされています。
以下では、ツイッターでLAMBDA以降の関数を使用した例題に取り組んだものを順次追加しています。
したがって掲載している数式は特に吟味した数式であるとか、定番のやり方だという事ではありません。
新関数がでたので、練習がてら問題に取り組んだものを記事として残したものと捉えてください。
目次
2つの1次元配列から、それをクロス結合した結果を返す
https://twitter.com/yamaoka_ss/status/1559069253344497664
MAP(
SEQUENCE(COUNTA(x)*COUNTA(y),2),
LAMBDA(z,
IF(ISODD(z),
INDEX(x,QUOTIENT(z/2,COUNTA(y))+1),
INDEX(y,MOD(z/2-1,COUNTA(y))+1)))))(A2:A5,B1:D1)
縦,A2:A5,
横,B1:D1,
MAKEARRAY(COUNTA(縦)*COUNTA(横),2,
LAMBDA(x,y,
IF(y=1,
INDEX(縦,QUOTIENT(x+COUNTA(横)-1,COUNTA(横))),
INDEX(横,MOD(x-1,COUNTA(横))+1)))))
正直なんだかなーというきしかしない・・・
また、そのうち考えることにします。
とりあえず、はけたさんの数式が簡単で良さそうなので、必要な時はそれを使うという事で。
https://twitter.com/excelspeedup/status/1558650046195048451
https://twitter.com/excelspeedup/status/1563025515329384448
LET(tc,LAMBDA(x,y,TOCOL(x&IF(y=y,""))),
HSTACK(tc(r,c),tc(c,r))
)
)(A2:A4,B1:E1)
縦*縦の場合は、引数でTOROWすれば良いと思います。
数式の中に入れることもできますが、数式が見づらくなってしまいます。
A列が同じ行のB列の値を連結して、A列の一意な値とともに出力
※添付画像は365insiderの新関数を使って作りました。
※insider新関数使わずに作れるかは分かりません。
a,A1:A12,
b,B1:B12,
uq,UNIQUE(a),
HSTACK(
uq,
MAP(uq,LAMBDA(x,CONCAT(FILTER(b,a=x))))
))
名前定義を使わずにLAMBDA関数で再帰する方法
https://twitter.com/yamaoka_ss/status/1555177131759398912
=LET(
Z, LAMBDA(f, LET(g, LAMBDA(x, f(LAMBDA(v, LET(xx, x(x), xx(v) )))), g(g))),
MYLOVE, Z(LAMBDA(RECUR, LAMBDA(x, IF(RIGHT(x,24)=REPT("ドドスコスコスコ",3),x&"ラブ注入",RECUR(x&IF(RANDBETWEEN(0,1),"ドド","スコ")))))),
MYLOVE("")
)
ちょっと理解不能ではあります。
文字列を大文字小文字変換して大小文字の全組み合わせを出力
https://twitter.com/yamaoka_ss/status/1561573944976556032
A1に入力されている英文字列
この文字列を大文字小文字変換して大小文字の全組み合わせを出力(出力数=2^文字数)してください。
※特に制限なし。新旧関数および作業列なんでもあり
副題として「※新関数を覚えよう編」なので、新関数の練習に取り組んでもらえれば良いかなという出題でした。
後は手法として、LOWER,UPPERを使う、文字コードを使う、これらは古くからあるものですね。
a,A1,
LN,LEN(a),
LW,LOWER(MID(A1,SEQUENCE(,LN),1)),
UP,UPPER(LW),
ary,IF(MAKEARRAY(2^LN,LN,LAMBDA(x,y,MID(DEC2BIN(x-1,LN),y,1)))*1=0,LW,UP),
BYROW(ary,LAMBDA(x,CONCAT(x)))
)
あまりすっきり書けていない感じもしますが、一例として。
2つのテーブルの片方しかない行を縦に連結出力
シートに「テーブル1」と「テーブル2」があります。
片方にしかない行を抽出して縦に並べてください。
idがキーで、役職、氏名は一意に決まっているものとします。
※添付参照してください。
どっちのテーブルに存在しているかを一覧の後ろに出力。
"テーブル1","テーブル2"でも"左","右"でも分かれば良し。
※添付画像を参照
追加お題の引用リツイートにより寄せられた回答
=LET(
uq,UNIQUE(VSTACK(テーブル1,テーブル2),,TRUE),
HSTACK(uq,IF(COUNTIFS(テーブル1[id],CHOOSECOLS(uq,1)),"左","右"))
)
私の作成した数式は、
=UNIQUE(VSTACK(テーブル1,テーブル2),,TRUE)
まあ、この問題が答えありきだったかも…
このように、最新関数で今までは出来ない(出来てもとても難しい数式)がこうもすっきり書けるようになるんですね。
=LET(
uq,UNIQUE(VSTACK(テーブル1,テーブル2),,TRUE),
HSTACK(uq,IF(COUNTIFS(テーブル1[id],CHOOSECOLS(uq,1)),"左","右"))
)
これは書き方がいろいろありそうですね。
いずれにしても、以前に比べれば格段に簡単な数式にはなると思います。
3連単、3連複のフォーメーション買目を全て列挙する
3連単
3連複
この組み合わせの列挙・組み合わせ数を返す数式に再チャレンジ
うーん、ムズイ、すっきりいかない、結局ゴリ押ししかない・・・
02,03→03,01,04→01,05,02,04 ・・・ 13通り
02,03-03,01,04-01,05,02,04 ・・・ 9通り
数式が長くて140文字超えているので貼り付けられない・・・
in,IFNA(TEXTSPLIT(A1,",",dl),""),
in_1,SORT(CHOOSEROWS(in,1),,,TRUE),
in_2,SORT(CHOOSEROWS(in,2),,,TRUE),
in_3,SORT(CHOOSEROWS(in,3),,,TRUE),
in_t1,FILTER(in_1,in_1<>""),
in_t2,FILTER(in_2,in_2<>""),
in_t3,FILTER(in_3,in_3<>""),
in_12,TOCOL(in_t1&dl&TOCOL(in_t2)),
out,TOCOL(in_12&dl&in_t3),
FILTER(out,(MID(out,1,2)<>MID(out,4,2))*(MID(out,1,2)<>MID(out,7,2))*(MID(out,4,2)<>MID(out,7,2)))
)
さらに長くなった・・・
in,IFNA(TEXTSPLIT(A1,",",dl),""),
in_1,SORT(CHOOSEROWS(in,1),,,TRUE),
in_2,SORT(CHOOSEROWS(in,2),,,TRUE),
in_3,SORT(CHOOSEROWS(in,3),,,TRUE),
in_t1,FILTER(in_1,in_1<>""),
in_t2,FILTER(in_2,in_2<>""),
in_t3,FILTER(in_3,in_3<>""),
in_12,TOCOL(in_t1&dl&TOCOL(in_t2)),
out,TOCOL(in_12&dl&in_t3),
out_2,FILTER(out,(MID(out,1,2)<>MID(out,4,2))*(MID(out,1,2)<>MID(out,7,2))*(MID(out,4,2)<>MID(out,7,2))),
out_3,MAKEARRAY(COUNTA(out_2),3,(LAMBDA(x,y,MID(CHOOSEROWS(out_2,x),(y-1)*3+1,2)))),
UNIQUE(BYROW(out_3*1,LAMBDA(x,TEXT(MIN(x),"00"&dl)&TEXT(SMALL(x,2),"00"&dl)&TEXT(MAX(x),"00"))))
)
3連単
i,TEXTSPLIT(A1,",",dl,,,""),
c,LAMBDA(n,SORT(CHOOSEROWS(i,n),,,1)),
f,LAMBDA(a,FILTER(a,a<>"")),
p,LAMBDA(x,y,TOCOL(TOCOL(x)&dl&TOROW(y))),
t,p(f(c(1)),f(c(2))),
o,TOCOL(t&dl&f(c(3))),
m,LAMBDA(x,y,MID(o,x,2)<>MID(o,y,2)),
FILTER(o,m(1,4)*m(4,7)*m(7,1))
)
i,TEXTSPLIT(A1,",",dl,,,""),
c,LAMBDA(n,SORT(CHOOSEROWS(i,n),,,1)),
f,LAMBDA(a,FILTER(a,a<>"")),
p,LAMBDA(x,y,TOCOL(TOCOL(x)&dl&TOROW(y))),
t,p(f(c(1)),f(c(2))),
o,TOCOL(t&dl&f(c(3))),
m,LAMBDA(x,y,MID(o,x,2)<>MID(o,y,2)),
q,FILTER(o,m(1,4)*m(4,7)*m(7,1)),
r,MAKEARRAY(COUNTA(q),3,(LAMBDA(x,y,MID(CHOOSEROWS(q,x),(y-1)*3+1,2)))),
UNIQUE(BYROW(r*1,LAMBDA(x,TEXT(MIN(x),"00"&dl)&TEXT(SMALL(x,2),"00"&dl)&TEXT(MAX(x),"00"))))
)
FILTER関数の出力行数・列数を指定する
A:Cの表からA列=F1で絞り込み、かつ、F2行数F3列数に減らして出力してください。
ただし、F2,F3が実際より大きい数字の時にはエラーにせずA列絞り込みのまま出力してください。
※添付参照してください。
数式は、
f,FILTER(A:C,A:A=F1),
INDEX(f,SEQUENCE(MIN(F2,ROWS(f))),SEQUENCE(1,MIN(F3,COLUMNS(f))))
)
行列数を大きい数字指定した時にエラーにしないというのが面倒ですね。
月が縦で日が横の表を、曜日(7列)で縦に折り返す
元データは、月が縦で日が横になっいます。
これを週で折り返した表に変換してください。
A2セルの値を開始日としてください。
B7セルから、月~日で下に折り返して出力です。
※添付画像参照
in,TOROW(B2:AF4,1),
pd,"",
bf,MAKEARRAY(1,WEEKDAY(A2,3),LAMBDA(x,y,pd)),
WRAPROWS(HSTACK(bf,in),7,pd)
)
in,TOROW(B2:AF4,1),
pd,"",
bf,EXPAND("",1,WEEKDAY(A2,3),pd),
WRAPROWS(HSTACK(bf,in),7,pd)
)
以下では月曜開始に対応しています。
LAMBDA以降の新関数の問題集-なぜわざわざそうしたいのか編
文字列内の括弧()()の中の文字を取り出して列挙
A1文字列の()()の中の文字を取り出して列挙してください。
括弧の全角半角は区別せず、どっちが使われていても良しとする。
作成した数式は、
ds,{"(","("},
de,{")",")"},
s,TEXTSPLIT(A1,ds),
t,MAP(s,LAMBDA(x,TEXTBEFORE(x,de,,,,""))),
FILTER(t,t<>"")
)
作成された配列の先頭(TEXTAFTERを使うなら最後)の空白や、
文字列中に括弧が対になっていない場合を考慮して、FILTERで排除するように数式を組んでみました。
表内にあるセル内改行を複数行に展開
出題内容については以下を参照してください。
表1を表2に変換してください。
・手作業
・シート数式
・パワク
・VBA
なんでもあり、とにかく作れと言われました。
(という設定でw)
※というか、私はまだ答えを持っていないw
表2は、セル内改行を縦に展開して、空欄は上セルと同値にする。
これはもう無茶ですね。
不足部分の埋め方が、最初の改行前の文字列を埋めているのでサンプルと違ってしまった。最後の改行以降をとるのって…
VBAが良いですね。
あれ、これってパワクで出来るのですか?私は知らない・・・
改行数,MAP(in,LAMBDA(x,LEN(x)-LEN(SUBSTITUTE(x,CHAR(10),""))+1)),
最大改行数,BYROW(改行数,LAMBDA(x,MAX(x))),
改行不足,最大改行数-改行数,
改行揃え,LAMBDA(x,y,z,x&REPT(CHAR(10)&TEXTBEFORE(x,CHAR(10),,,,x),y))(in,改行不足,改行数),
全結合,REDUCE("",TRANSPOSE(改行揃え),LAMBDA(x,y,x&IF(x="","",CHAR(10))&y)),
WRAPCOLS(TEXTSPLIT(全結合,CHAR(10)),SUM(最大改行数))
)
TEXTBEFORE(x,CHAR(10),,,,x)
↓
TEXTAFTER(x,CHAR(10),-1,,,x)
TEXTBEFOREまたはTEXTAFTERの部分を消せば良いです。
というか、出題としてはこれを出した方が良かった気がしなくもない・・・
文字列の中から1文字削除の全パターン出力
脱字メーカー
A列の文字列から1字消した全パターンを出力して下ください。
普通に数式を書く場合については以下を参照してください。
脱字メーカー(文字列から1文字削除)
=LAMBDA(x,
LET(
L,LEN(x),
vs,SEQUENCE(L),
hs,SEQUENCE(,L),
ar,MID(x,vs,1),
vh,LAMBDA(x,y,IF(x=y,0,x)),
BYCOL(vh(vs,hs),LAMBDA(x,CONCAT(FILTER(ar,x)))))
)(A1)
無駄に難しくしてしまったか😅
vh,LAMBDA(x,y,IF(x=y,0,x))
この関数にSEQUENCE(L)と,SEQUENCE(,L)、つまり縦配列と横配列を入れることで2次元の配列を作成しています。
BYCOL(vh(vs,hs),LAMBDA(x,CONCAT(FILTER(ar,x))))
この配列をBYCOLで列ごとに処理させてFILTERで0を除いています。
これで1文字ずつの縦配列を作成。
この配列をFILTERの引数「配列」に入れて、「含む」に先の2次元の数列からBYCOLで1列ずつ取り出しながら入れていきます。
BYCOL(vh(vs,hs),LAMBDA(x,CONCAT(FILTER(ar,x))))
FILTERの結果をCOCATでつなげて完成です。
クロスABC分析
クロスABC分析を作成
片方だけなら別セルでやっても良いけど2つは面倒…
ということで、
売上や粗利の数値範囲を指定することでABCに分けられる数式を作成してください。
※<=70%:A、<=90%:B、>90%:C
※作成方法は添付2枚目参照
ランク境界の同値や、<=70%と<70%の違いを気にしなければこれで。
(そのような数値になる事は稀ですし問題にならない場合も多い)
=XLOOKUP(SUMIFS(B2:B11,B2:B11,">="&B2:B11)/SUM(B2:B11),{0;0.7;0.9},{"A";"B";"C"},,-1)
=LAMBDA(x,
LET(入力,x,
順序,SEQUENCE(ROWS(入力)),
配列,SORT(HSTACK(入力,順序),,-1),
累計,SCAN(0,CHOOSECOLS(配列,1),LAMBDA(x,y,x+y)),
ABC,MAP(累計/TAKE(累計,-1,-1),LAMBDA(x,IFS(x<=0.7,"A",x<=0.9,"B",TRUE,"C"))),
SORTBY(ABC,CHOOSECOLS(配列,2)))
)(B2:B11)
元の順序の確保。
ROW()だけでは配列を入れた時に動かないので。
対象数値と入力順で2次元配列を作成。
出題としてはここがメインでした。
累積する時にSCANを使います。
配列の上から順次足し上げていきます。
最初の説明の通り、XLOOKUP等の近似値では<70%になってしまうのでIFSで処理。
TAKE(累計,-1,1)はSUM(入力)でも良いが、せっかくなのでTAKEを使用。
合計は先に変数作成しておいた方が数式は読みやすいかも。
元の入力順に戻して完成です。
案外この処理が面倒で、ここの工夫の仕方で大きく数式が変わって来るようです。
SCANを使う目的の問題としては大げさになってしまったかもしれません。
対応方法はいろいろありそうですが、
(FILTER(B:B,($A:$A<>"")*(ROW($A:$A)>1)))
今回の場合であればB列空欄があるのかないのか…
さすがにA列が空欄と言うのは無いのでこれで判定すれば良いと思います。
月利が毎月変動する月複利の計算
毎月変動する利率で月複利の計算です。
日割はしません。
開始日は月初、終了日は月末が指定されるとして、月単位の計算のみ。
※利率は年利です。
※利息円未満は切り捨て。
※画像1の利率は乱数ですが一応ALTに。
※画像2は検算
1,3.85%,3.98%,4.83%
2,4.65%,4.72%,4.37%
3,3.09%,4.86%,4.01%
4,4.42%,3.01%,4.80%
5,4.15%,3.46%,4.51%
6,3.35%,3.65%,3.14%
7,3.56%,4.16%,4.10%
8,3.22%,4.09%,4.33%
9,4.26%,4.69%,3.70%
10,3.62%,3.04%,3.29%
11,4.21%,4.76%,3.46%
12,3.68%,3.45%,4.51%
なんと専用関数がありました😅
ただし期間途中で端数処理をしない方式なので、実際に使う場面においてそれで良いのかどうか、私にはそこは分かりません。
また、結局は利率配列の不要部分の処理等が必要なのでその部分が面倒になりそうです。
https://twitter.com/mikimomo_as/status/1568224255304962048
=LAMBDA(入金,金利,開始,終了,LET(
年月,EOMONTH(開始,SEQUENCE(DATEDIF(開始,終了,"m")+1)-1),
月利,INDEX(金利,MATCH(MONTH(年月),TAKE(金利,,1),0),MATCH(YEAR(年月),TAKE(金利,1),0))/12,
REDUCE(入金,月利,LAMBDA(x,y,x+INT(x*y))))
)(H2,A1:D13,G2,G3)
横に年、縦に月の利率から当該月の利率を取得する部分の方が面倒な数式になってしまいます。
年月,EOMONTH(開始,SEQUENCE(DATEDIF(開始,終了,"m")+1)-1),
これで、開始日から終了日までの月末日の配列を作成しています。
開始日から終了日までの月利(年利/12)の配列を作成しています。
定番のINDEX+MATCH+MATCH
この問題でやったアンピボットを使って縦展開してからFILTERしても良いと思います。
https://twitter.com/yamaoka_ss/status/1567084986859425792
この問題の核心部分です。
REDUCEは配列を順次処理して合計を求めたりする場合に使います。
LAMBDA関数次第なので、数値合計だけではなくいろいろな処理を書くことができます。
こちらの解答でも使いました。
https://twitter.com/yamaoka_ss/status/1563808818433499136
レーベンシュタイン距離
LET(
a,SEQUENCE(1,x,0),
b,SEQUENCE(y,1,0),
IF(-a=b,0,IFS(a=0,b,b=0,a,TRUE,0))
))(5,4)
(すみません、私は寝てしまいました。)
素晴らしいですね。
https://twitter.com/ksgiksg/status/1576673876603387904
(内部の数式は手を付けずにそのままにしています。)
=LAMBDA(strA,strB,LET(
lenA,LEN(strA),lenB,LEN(strB),
arrA,HSTACK("",MID(strA,SEQUENCE(1,lenA),1)),
arrB,HSTACK("",MID(strB,SEQUENCE(1,lenB),1)),
初期配列,IFERROR(VSTACK(SEQUENCE(1,lenA+1,0),SEQUENCE(lenB)),0),
結果配列,REDUCE(
初期配列,
SEQUENCE((lenA)*(lenB)),
LAMBDA(arr,i,
LET(
A,MOD(i-1,lenA)+1,
B,INT((i-1)/lenA)+1,
txA,INDEX(arrA,A+1),
txB,INDEX(arrB,B+1),
①,INDEX(arr,B,A+1)+1,
②,INDEX(arr,B+1,A)+1,
③,INDEX(arr,B,A)+(txA<>txB),
min,MIN(①,②,③),
拡張,IFERROR(VSTACK(EXPAND(0,B,lenA+1,0),HSTACK(EXPAND(0,lenB-B+1,A),min)),0),
arr+拡張
)
)
),
INDEX(結果配列,lenB,lenA)))(A1,B1)
文字列を数字と数字以外で分割
なんだかずいぶん前のような気がします。
「エクセル問題」等でこれの最新関数使用バージョンは既にやっていますか?
もし既に出ているなら教えてもらえると嬉しい。
もしまだなら、このまま問題として出しておきます。
※↓この時は、ちゅんさんが作ってくれました。
セルに文字数値の組み合わせで入っている値を、別セルに文字と数値に分割する。
ab123→abと123に分割・・・これは難しいができるはず
ab123DEF45→ab,123,DEF,45・・・これが可能できるか
ちなみに、私には無理w
引用リツイートにより寄せられた回答
=LAMBDA(セル,LET(
分割,MID(セル,SEQUENCE(LEN(セル)),1),
isN,LAMBDA(x,ISNUMBER(x*1)),
区切,SCAN(TAKE(分割,1),分割,LAMBDA(x,y,IF(isN(RIGHT(x))=isN(y),y,CHAR(1)&y))),
配列,TEXTSPLIT(CONCAT(区切),CHAR(1)),
IFERROR(配列*1,IFERROR(配列,""))))(A1)
※ツイートに収まった😇
isNを関数にしたところ以外は特に工夫もないですね。
そのまま素直に書いてみた感じです。
=LAMBDA(セル,LET(
分割,MID(セル,SEQUENCE(LEN(セル)-1)+1,1),
isN,LAMBDA(x,ISNUMBER(x*1)),
区切,REDUCE(LEFT(セル),分割,LAMBDA(x,y,IF(isN(RIGHT(x))=isN(y),x&y,x&CHAR(1)&y))),
配列,TEXTSPLIT(CONCAT(区切),CHAR(1)),
IFERROR(配列*1,IFERROR(配列,""))))(A1)
いろいろ工夫できると思います。
縦横スピルしないXLOOKUP代替(MATCH+INDEX,FILTER,CHOOSEROWS)
縦横スピルしないXLOOKUP代替(MATCH+INDEX,FILTER,CHOOSEROWS)
直積(クロス結合、交差結合)とピボット解除
直積(クロス結合、交差結合)とピボット解除
同じテーマ「エクセル入門」の記事
TEXTSPLIT関数(列と行の区切り記号で文字列を分割)
TEXTBEFORE関数(テキストの指定文字列より前の部分を返す)
TEXTAFTER関数(テキストの指定文字列より後ろの部分を返す)
LAMBDA以降の新関数の使用例
縦横スピルしないXLOOKUP代替(MATCH+INDEX,FILTER,CHOOSEROWS)
直積(クロス結合、交差結合)とピボット解除
複数の文字列を検索して置換するSUBSTITUTE
LAMBDA以降の新関数の問題集
LAMBDA以降の新関数の問題と解説(ヘルパー関数編)
LAMBDA以降の新関数の問題と解説(配列操作関数編)
PY関数(Pythonコードをセル内で実行)
新着記事NEW ・・・新着記事一覧を見る
TRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)
正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)
エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)
ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.繰り返し処理(For Next)|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.変数宣言のDimとデータ型|VBA入門
5.RangeとCellsの使い方|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.セルのクリア(Clear,ClearContents)|VBA入門
8.メッセージボックス(MsgBox関数)|VBA入門
9.条件分岐(Select Case)|VBA入門
10.ブック・シートの選択(Select,Activate)|VBA入門
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。