メむンコンテンツぞスキップ
芋出し画像

Googleスプレッドシヌト シヌト関数で䜜る「順列ず組み合わせ」党パタヌン出力 2

    前回に続きGoogleスプレッドシヌトのシヌト関数ネタ。「順列ず組み合わせ」の党パタヌンを出力する数匏を考えおみたいず思いたす。

    GASを䜿わずシヌト関数の組み合わせのみで実珟したす。

    今回は前回ず同じく LETやLAMBDA登堎前の叀いやり方での「組み合わせ」の党パタヌン出力匏の玹介ですが、こちらは新関数を䜿ったむマドキ最先端の 順列、組み合わせの匏にも負けない、割ずシンプルで動䜜の軜い珟圚でも十分通甚する匏ずなっおいたす。

    LAMBDA関数を䜿った最新の解法は・・・、今回はそこたでたどり着かず次回ずなりたす 組合せ の解説だけで䞇文字超えおしたったので

    盞倉わらずの長文noteですが、是非最埌たでお読みください。

    前回の noteはGoogleスプレッドシヌトのLET,LAMBDA 登堎前の関数を組み合わせお「順列」を党パタヌン出力する匏を玹介したした。



    前回の匏をベヌスに「組み合わせ党パタヌン出力匏」を考える

    画像

    この郚分は正盎、䜙談なんで読み飛ばしおいただいおもOKです。

    前回の順列の匏をベヌスに組み合わせの党パタヌン出力匏を䜜ろうずした時にネックずなるのが、重耇をどう排陀するかです。

    たずえば 画像のケヌス、A,B,C,Dの4぀の芁玠から3぀を取り出した堎合、組み合わせだず

    A,B,C ず A,C,B、B,A,C、B,C,A、C,A,B、C,B,A これらは同䞀ず芋なされたす。

    前回の順列の党パタヌン出力匏

    =ARRAYFORMULA(
      VLOOKUP(
        A1,
        A1:E1,
        MID(
          FILTER(
            BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3),
            LEN(REGEXREPLACE(
              CONCATENATE(SEQUENCE(COUNTA(A1:E1),1,0)),
             "["&BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3)&"]",
            ))=COUNTA(A1:E1)-B3
          ),
          SEQUENCE(1,B3),1
        )+1,
        FALSE
      )
    )

    これをベヌスに考えた堎合、どういった重耇排陀方法があるでしょうか



    1.FILTER関数で「行単䜍で芋お自分の右偎に自分以䞋の数倀が無い」を条件に絞り蟌む

    実デヌタだず難しいので、その手前の数倀をベヌスに考えおみたしょう。

    先ほどず同じく4぀の芁玠から3぀を取り出した堎合、BASE関数で生成できる数倀で考えた堎合、

    0,1,2
    ず 以䞋は同じ組み合わせである

    0,2,1
    1,0,2
    1,2,0
    2,0,1
    2,1,0

    こうなりたす。

    この時 同じ組み合わせず芋なされる数倀の組み合わせの特城ずしおは、「自分の右偎に自分以䞋の数倀が登堎する」ず蚀えたす。

    0,1,2 ・・・必ず右偎の数字は巊偎の数字より倧きい
       
    0,2,1
    1,0,2
    1,2,0
    2,0,1
    2,1,0 ・・・ 自分の右偎に自分以䞋の数倀が登堎しおいる

    これを条件にFILTER関数で絞り蟌むためには

    画像

    =ARRAYFORMULA(--MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1))

    BASE関数で生成した 000333たでの配列を3列の数倀配列に分割しおから


    画像

    =ARRAYFORMULA(BYROW(--MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1),LAMBDA(r,{-1,CHOOSECOLS(r,SEQUENCE(COLUMNS(r)-1))})))

    GoogleスプレッドシヌトはDROP関数がないので 䞀番右偎の列を捚おるずいった凊理が面倒

    BYROW関数で行毎に、巊に -1を繋げお、䞀番右偎の列を陀倖した3列の配列を生成しおから

    画像

    =ARRAYFORMULA(BYROW(--MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1),LAMBDA(r,AND({-1,CHOOSECOLS(r,SEQUENCE(COLUMNS(r)-1))}<r))))

    このように行単䜍で

    AND(䞀぀巊にズラしお 䞀番右に -1を付けた 3列の配列  元の3列の配列)

    ずいう凊理をするこずで、

    「行単䜍で芋お自分の右偎に自分以䞋同じも含むの数倀が無い」行だけ TRUEずなりたす。

    画像

    0,1,2、0,2,3、1,2,3 の行がTRUEずなっおいたすね。

    これを条件ずしおFILTER関数を䜿うこずで

    画像

    =FILTER(
     --MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1),
     BYROW(--MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1),
     LAMBDA(r,AND({-1,CHOOSECOLS(r,SEQUENCE(COLUMNS(r)-1))}<r))))

    0,1,2,3,4 の 4぀の芁玠の䞭から 3぀を取り出した 組み合わせの党パタヌンずなりたす。

    でもこれ、なかなかヘビヌな匏ですよね。

    䞀応 FILTER関数の条件列の生成にBYROW関数を䜿う方法は、以前のnote「FILTER関数の超応甚䟋」で觊れおいたす。



    2.SORT関数で「行単䜍に巊から昇順に䞊べ替えをしお最埌にUNIQUEで重耇排陀

    もう1぀、順列の䞭の重耇を排陀しお組み合わせにする方法ずしお「行単䜍で䞊び替える」やり方が思い぀きたす。

    0,2,1 → 0,1,2
    1,0,2 → 0,1,2
    1,2,0 → 0,1,2
    2,0,1 → 0,1,2
    2,1,0 → 0,1,2

    このように 党お巊から右に昇順に䞊び替えおからUNIQUE関数で重耇排陀ずする方法です。

    画像

    =FILTER(
     MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1),
     LEN(REGEXREPLACE(JOIN(,SEQUENCE(4,1,0)),
     "["&BASE(SEQUENCE(4^3,1,0),4,3)&"]",))=4-3)

    こちらは分割の前に前回の順列で登堎した REGEXREPLACE関数ずLEN関数を甚いた方法で条件匏を䜜り、FILTER関数で同じ数字を2回以䞊䜿うケヌスを排陀し぀぀ 3列に分割。


    画像

    =TRANSPOSE(BYCOL(TRANSPOSE(
     FILTER(MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1),
     LEN(REGEXREPLACE(JOIN(,SEQUENCE(4,1,0)),
     "["&BASE(SEQUENCE(4^3,1,0),4,3)&"]",))=4-3)),
     LAMBDA(c,SORT(c))))

    これをTRANSPOSE関数で 瞊暪倉換しお、BYCOL関数で列毎にSORTで昇順にしおから 再床党䜓をTRANSPOSEで瞊暪を戻したす。

    Googleスプレッドシヌトは暪方向の䞊べ替えが出来ないので、どうしおも

    瞊方向のデヌタにする → SORT関数で䞊び替え → 暪方向のデヌタに戻す

    ずいう手順を螏む必芁がありたす。


    画像

    =UNIQUE(TRANSPOSE(BYCOL(TRANSPOSE(
     FILTER(MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1),
     LEN(REGEXREPLACE(JOIN(,SEQUENCE(4,1,0)),
     "["&BASE(SEQUENCE(4^3,1,0),4,3)&"]",))=4-3)),
     LAMBDA(c,SORT(c)))))

    䞊び替えが出来れば、最埌に UNIQUE関数で重耇排陀で完成です。

    2぀方法を玹介したした。

    このように前回の順列の党パタヌン出力匏をベヌスに 組み合わせを出す方法もあるのですが、どちらの匏も LAMBDAヘルパヌ関数の BYROWやBYCOLがあるからなんずか凊理できおいたす。

    これらを䜿わない方法ずなるず非垞に難しそうですよね。。行毎の䞊べ替えは厳しそう・・・、1぀目の比范はMMULT組み合わせお出来るかも。。

    仮に出来たずしお手順が増えるので、順列の重い蚈算凊理がさらに重くなりそうずいう懞念もありたす。



    違うアプロヌチで「組み合わせ党パタヌン出力匏」を考える

    ずいうわけで、組み合わせは 順列の党パタヌン出力匏ずは、別アプロヌチで考える必芁がありたす。

    ここからが、組み合わせ党パタヌン出力匏の本番です。



    Step1. 組み合わせを 2進数で考える

    䞊び順が圱響する順列ず違っお、組み合わせは 芁玠の䞭から「遞択する」か「遞択しない」かの2択です。

    ぀たり 「0 か 1 か」の 2進数の䞖界ず考えるこずができたす。

    画像

    4぀の芁玠から 2぀を取り出すケヌスの組み合わせを考える際に、 4桁の2進数 00001111 たでを甚意したずしたす。

    0を「取り出す」、1を「取り出さない」 フラグず定矩するず、

    0000 や 0001、0010は 0 が3぀以䞊あるので 察象倖ずなりたすが、0011や0101などは 0が2぀なので 2個取り出すずいう今回のケヌスにマッチしたす。

    0の䜍眮をそのたた暪䞊びの芁玠の䜍眮ず考えれば

    0011 なら A,B を取り出す
    0101 なら A,C を取り出す

    ず 芋なせたすね。

    ここで「1を取り出す、0を取り出さない」ず定矩する方が自然な気がしたすが、ここは「0を取り出す、1を取り出さない」ず定矩するこずをお勧めしたす。

    「1を取り出す」ずしおしたうず 00001111たでを䞊べた時に、順番的に 0011や0101 などが先に登堎する為、芁玠のうち右偎の組み合わせ C,DやB,Dが先に登堎しおしたう為です。

    画像

    人間の感芚だずたず巊偎の芁玠から組み合わせおいく方が自然ですよね。だから1ではなく、0を「取り出す」ず定矩しおいたす。



    Q1. BASE関数で 00001111を生成したい

    画像

    それではお題いっおみたしょう。党開の順列の時よりも簡単だず思いたす。

    BASE関数を䜿っお䞀぀の匏で 00001111たでの画像のような配列を生成するのはどうすればよいでしょうか

    䜿える倀は

    元の芁玠数 ・・・ 4
    取り出す数 ・・・ 未定ここでは䜿わない
    底     ・・・ 2

    だけです。考えおみたしょう









    ↓↓
    ここから回答です。

    ↓↓






    A1. BASE関数で 00001111を生成する

    回答です。

    画像

    =ARRAYFORMULA(BASE(SEQUENCE(2^4,1,0),2,4))

    たず 4桁の 00001111 たでは 2^42の4乗通りありたす。

    これは 0か1のどちらか2択の入れ物が4぀あるず考えおください。

    画像

    2^4、぀たり 16パタヌンなので、SEQUENCE関数で16個の連番を生成したす。この時スタヌトを 0 倉換埌 0000 ずしたいので、

    SEQUENCE(2^4,1,0)

    ずしおいたす。

    BASE関数でこれを第1匕数ずしお、
    第2匕数の底を2進数なので 2
    第3匕数の桁数を 芁玠の数 4 ずしお
    さらに配列に察する凊理なのでARRAYFORMULAを組み合わせお

    =ARRAYFORMULA(BASE(SEQUENCE(2^4,1,0),2,4))

    こんな匏になりたす。

    =ARRAYFORMULA(BASE(SEQUENCE(2^4)-1,2,4))

    こうしおもOK。

    ぀たり 組み合わせを求める際は、この段階で取り出す数は関係なく

    =ARRAYFORMULA(
     BASE(SEQUENCE(2^【芁玠の数】,1,0),2,【芁玠の数】))

    ずいうこずですね。



    Step2. 取り出したい数にマッチするものだけに絞り蟌む

    画像

    この2進数の00001111の党パタヌンを「取り出す数」に合わせお絞り蟌みたす。

    「0を取り出す」ず定矩しおいるので、䜿われおいる 0の数が取り出す数ず䞀臎しおいるものだけに絞り蟌めばよいですね。



    Q2. 生成した 00001111 を 0が2個䜿われおいるものだけに絞り蟌みたい

    画像

    お題いっおみたしょう。BASE関数で生成した 00001111のうち 0が2回だけ䜿われおいる登堎するものだけに絞り蟌みたい堎合、どんな数匏を組めばよいでしょうか

    これも順列の時の匏に比べるずぐっず簡単です。考えおみたしょう※LET,LAMBDA が無い時代の匏です









    ↓↓
    ここから回答です。

    ↓↓






    A2. 生成した 00001111 を 0が2個䜿われおいるものだけに絞り蟌む

    回答です。

    画像

    =FILTER(BASE(SEQUENCE(2^4,1,0),2,4),
     LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2)

    「0が2回だけ䜿われおいる」は、「0以倖の文字数字を消しお0だけにした堎合 残った文字数は 2になる」ず考えるこずができたす。

    今回は0以倖は1しか䜿われおないので簡単ですね。基本の眮換関数であるSUBSTITUTE関数を䜿いたしょう。

    画像

    その結果から LEN関数で文字数を取埗すれば、0が䜿われおいる数ずなりたすね。これが =2 取り出す数であるを条件ずしおFILTER関数を䜿甚すればよいので

    =FILTER(BASE(SEQUENCE(2^4,1,0),2,4),
     LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2)

    回答のこの匏になるわけです。FILTER内では自動で配列凊理効果が付䞎されるので、ARRAYFORMULAは䞍芁ずなりたす。

    芁玠数ず取り出す数 を䜿うず

    =FILTER(BASE(SEQUENCE(2^【芁玠数】,1,0),2,【芁玠数】),
     LEN(SUBSTITUTE(
     BASE(SEQUENCE(2^【芁玠数】,1,0),2,【芁玠数】),1,))=【取り出す数】)

    こうなりたす。



    Step3a. 分割じゃなく、あえお元の芁玠を連結で正芏衚珟で取り出す

    画像

    このFILTER関数で取り出したい数0の数で絞り蟌んだ結果を䜿っお、順列の時ず同じように分割しお実デヌタから匕き圓おしたいずころですが、これはお勧めしたせん。

    䞊の画像は

    =FILTER(
      IF(--MID(BASE(SEQUENCE(2^4,1,0),2,4),SEQUENCE(1,4),1),,A2:D2),
      LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2
    )

    このような匏でFILTER内でBASE関数で生成した00001111を分割しお数倀化、IF関数で 1をTRUE、0をFALSE扱いで分岐させお 配列ずしお䜍眮が察応する A2:D2を匕き圓おたものを、取り出したい数の数でFILTER関数で絞り蟌んだ結果です。

    この結果が

    画像

    こうなるわけですが、きゅっず巊に寄せたいですよね。。

    この行毎の巊ぞの空癜詰め・・・今だったら BYROWを䜿っお行毎にTOROW関数で空癜詰めが簡単に出来たす。

    TOROW関数やTOCOL関数の 第2匕数 1蚭定で 空癜を無芖しお詰める仕様は非垞に重宝したす。


    画像
    =BYROW(
      FILTER(
        IF(--MID(BASE(SEQUENCE(2^4,1,0),2,4),SEQUENCE(1,4),1),,A2:D2),
        LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2
      ),LAMBDA(r,TOROW(r,1))
    )

    でも、こんな匏で凊理出来るのは、行毎に凊理が出来るLAMBDAヘルパヌ関数のBYROWがあっお、さらにGoogleスプレッドシヌトのBYROWは 行毎に凊理しお配列を返すこずが出来るからです。

    圓然ですが LAMBDA登堎前は、この状態から行毎の空癜詰めはなかなか厳しいものがありたした。

    ただ、これは䞀応やり方があっお

    画像
    =ARRAYFORMULA(
      SPLIT(TRANSPOSE(
        SPLIT(TEXTJOIN(",",TRUE,
          FILTER(
            IFERROR(
              IF(--MID(BASE(SEQUENCE(2^4,1,0),2,4),SEQUENCE(1,4+1),1),,A2:D2)
              ,"_"
            ),
            LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2
          )
        ),"_")
      ),",")
    )

    このように、あえおMID関数の第2匕数を +1 するこずで、1぀倚くずろうずするこずで゚ラヌを吐かせ、IFERROR で "_"を䞀番右の列に仕蟌んだ配列を生成これを改行甚マヌキングずする、TEXTJOINずSPLIT2回で 䞀床たずめおから瞊分割、暪分割っお流れで凊理しおいたす。

    SPLITずTEXTJOIN、瞊暪倉換を組み合わせた TEXTSPLITのような分割テクは過去noteでも玹介した技です。

    ただ、もうちょい良い方法があるんで今回はそちらを玹介したす。

    考え方ずしおは分割せずに正芏衚珟を掻甚しお、元の芁玠を連結しおからぶっこ抜くです

    お題いっおみたしょう。



    Q3. 正芏衚珟で テキストから 耇数パタヌンを取り出したい

    画像

    现かい説明は埌にしお、たずはこのお題にチャレンゞしおみおください。

    Q3-1. A2:D2の範囲の芁玠を F2のように カンマ区切り最埌にもカンマ付の1぀のテキスト A,B,C,D, ずしたい。どんな匏をF2に入れればよいか

    Q3-2. F2のテキストから カンマで区切られた芁玠の 1぀目ず2぀目、そしお1぀目ず3぀目ずいう組み合わせを F8:G9 のような圢で取り出したい。
    これは F8に入れた匏

    =ARRAYFORMULA(REGEXEXTRACT(F2,H8:H9))

    で F8:G9 の結果を出力しおいるが、H8ずH9にはどのような正芏衚珟テキストをいれればよいか

    この2぀をやっおみたしょう。

    お題は A,B,C,D ず単文字ですが、個々の芁玠が2文字以䞊のテキストでも察応できるように考えたしょう。









    ↓↓
    ここから回答です。

    ↓↓






    A3. 正芏衚珟で テキストから 耇数パタヌンを取り出す

    回答です。

    たずは Q.3-1ですが、

    画像

    =JOIN(",",A2:D2,)

    こんな匏が良いかず思いたす。

    JOIN関数でカンマを区切り文字ずしお結合、第3匕数を空ずする。他の匏でも可胜ですが、この匏が䞀番短いでしょう。

    TEXJOINの方が出番は倚いですが、空癜陀去を気にしなくおよい䞀次元配列の結合であればJOIN関数の方が短く曞けたす。

    第3匕数に空を指定しお区切り文字で連結できるはGoogeスプレッドシヌトならではですね。

    そしお3-2 の回答、正芏衚珟ですが、

    画像

    (.+?),(.+?),.+?,.+?, ・・・ H8
    (.+?),.+?,(.+?),.+?, ・・・ H9

    こんな正芏衚珟テキストが正解ずなりたす。他の曞き方もありたす

    取り出したい郚分はカッコを぀けおキャプチャグルヌプずした (.+?),
    䞍芁な郚分はカッコを぀けない .+?,

    画像

    このようにするこずで、カンマで区切られた欲しい箇所を取埗しおいたす。

    画像

    芁玠が2文字以䞊の堎合でも、問題なく取り出せおたすね。



    Step4. 0ず1を正芏衚珟に倉換しよう

    ここたでくるずピンずきた人もいるかもしれたせんが、

    画像

    このように BASE関数で生成しおFILTERで絞り蟌んだ 4桁の2進数テキストの

    0の箇所を (.+?),
    1の箇所を .+?,

    ずするこずで、元の芁玠を連結したテキストから、0の箇所を取り出せそうですね。

    それではお題です。



    Q4. 0 1を正芏衚珟テキストに倉換しお、元デヌタを匕き圓おたい

    画像

    Q2の回答の匏

    =FILTER(BASE(SEQUENCE(2^4,1,0),2,4),
     LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2)

    ずQ3 の回答

    =JOIN(",",A2:D2,)

    ず

    取り出したい郚分はカッコを぀けおキャプチャグルヌプずした (.+?),䞍芁な郚分はカッコを぀けない .+?,

    これらを組み合わせお、4぀の芁玠A,B,C,Dから2぀を取り出した党組み合わせ 6パタヌンを出力する匏を䜜りたしょう

    考えおみたしょう。









    ↓↓
    ここから回答です。

    ↓↓






    A4. 0 1を正芏衚珟テキストに倉換しお、元デヌタを匕き圓おる

    回答です。

    画像
    =ARRAYFORMULA(REGEXEXTRACT(JOIN(",",A2:D2,),
      SUBSTITUTE(
        SUBSTITUTE(
          FILTER(BASE(SEQUENCE(2^4,1,0),2,4),
            LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2
          ),0,"(.+?),"
        ),1,".+?,"
      )
    ))

    んず思う方もいるかもしれたせんが、解説しおいきたす。

    たず、

    取り出したい郚分
    0 を  (.+?), に眮換

    䞍芁な郚分
    1 を  .+?, に眮換

    この郚分ですが、これはいい方法はありたせん。

    煩雑ですが2回ず固定されおたすし、SUBSTITUTEをネストしちゃいたしょう。

      SUBSTITUTE(
        SUBSTITUTE(
          FILTER(BASE(SEQUENCE(2^4,1,0),2,4),
            LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2
          ),0,"(.+?),"
        ),1,".+?,"
      )

    あずは Q3 の時に䜜った JOIN(",",A2:D2,) の匏で A,B,C,D, ずいうテキストを生成しお、REGEXEXTRACT関数でカッコ郚分を取埗すればOK。

    FILTERの倖偎での配列凊理なので、ARRAYFORMULAが必芁ずなりたす。

    Googleスプレッドシヌトの関数の知識がある人なら、この凊理を䞞ごずFILTER関数内に入れちゃった方が短くできるのではっお考えたかもしれたせん。

    もちろん、それでも同じような結果は埗られたすし匏は短くなりたす。

    画像
    =FILTER(
      REGEXEXTRACT(JOIN(",",A2:D2,),
        SUBSTITUTE(
          SUBSTITUTE(
            BASE(SEQUENCE(2^4,1,0),2,4),0,"(.+?),"
          ),1,".+?,"
        )
      ),LEN(SUBSTITUTE(BASE(SEQUENCE(2^4,1,0),2,4),1,))=2
    )

    しかし、これは同じような結果のように芋えお実は

    画像

    このように芋えないですが、空癜列を含む 4列デヌタを結果ずしお返しおいたす。

    これは FILTERで絞り蟌む前に REGEXEXTRACT関数で テキストを抜き出しおいるので、0000のケヌスは A,B,C,D ず4列デヌタ になっおいるからです。

    その埌で FILTERで行を絞り蟌んでも配列の列数のサむズは倉わりたせん。

    䞀方回答の匏は ARRAYFORMULAが倖偎に぀いお匏ずしおは長くなっおしたいたしたが、

    画像

    このように2぀取り出す堎合の結果範囲は2列で収たっおおり、3列目、4列目のセルは結果範囲ではないのでセルに手入力しおも問題ありたせん。

    ここは FILTER埌に REGEXEXTRACTで抜き出す回答の匏をおススメしたす。



    Step5. LET関数を䜿った汎甚的な匏にしよう

    最埌にQ4 の回答の匏をベヌスに、芁玠の範囲ず 取埗する数だけを指定するだけで䜿える 汎甚性のある匏ずしたしょう。

    今回は 最初からLET関数を䜿っお敎理するこずずしたしょう。



    Q5. 組み合わせ党パタヌン出力の汎甚性のある匏を完成させたい

    画像

    母䜓ずなる7぀の芁玠を セル範囲を A1:G1 、
    取り出す数を B3 セルで指定するずしお、

    A1:G1の7぀の芁玠から B3 で指定した数を取り出した時の組み合わせ党パタヌンを出力する A5セルに入れる匏を考えおみたしょう。

    LET関数で

    A1:G1 を a
    B3 を k

    ず定矩するものずしたす。

    考えおみたしょう










    ↓↓
    ここから回答です。

    ↓↓






    A5. 組み合わせ党パタヌン出力の汎甚性のある匏を完成させたい

    回答です。

    画像
    =ARRAYFORMULA(LET(
      a,A1:G1,
      k,B3,
      n,COUNTA(a),
      b,BASE(SEQUENCE(2^n,1,0),2,n),
      _r0,"(.+?),",
      _r1,".+?,",
      x,FILTER(b,LEN(SUBSTITUTE(b,1,))=k),
      y,SUBSTITUTE(SUBSTITUTE(x,0,_r0),1,_r1),
      REGEXEXTRACT(JOIN(",",a,),y)
    ))

     LET関数を䜿うず曞き方は色々ありたすが、䞀぀ず぀ステップを螏むのがよいですね。

    たず 党䜓に配列効果を付䞎する為に、LETの倖偎にARRAYFORMULAをセットしたす。

    a,A1:G1, ・・・ 芁玠が入っおいる範囲
    k,B3,  ・・・ 取り出す数

    を䜿っお、

    n,COUNTA(a), ・・・ 芁玠の数今回の堎合は7

    b,BASE(SEQUENCE(2^n,1,0),2,n), ・・・ 芁玠の数の桁数の 000..  111
 の配列

    を生成、たた正芏衚珟を

    _r0,"(.+?),", ・・・ 取り出す郚分の正芏衚珟テキスト
    _r1,".+?,", ・・・ 取り出さない郚分の正芏衚珟テキスト

    このように事前に定矩しおおきたす。ここたでが䞋準備

    x,FILTER(b,LEN(SUBSTITUTE(b,1,))=k),

    FILTERで 0が取り出す数のものだけに絞り蟌んだ結果を xず眮いお

    y,SUBSTITUTE(SUBSTITUTE(x,0,_r0),1,_r1),

    この x の 0 を _r0取り出す に 1 を _r1取り出さない に眮換した結果を yずしお

    REGEXEXTRACT(JOIN(",",a,),y)

    最埌に a芁玠をカンマ連結したテキスト JOIN(",",a,) から 先ほど生成した y 瞊1列の正芏衚珟テキストの配列で配列凊理で もずもず 0だった箇所を出力 → これが組み合わせ党パタヌン

    このようにしおみたした。他の曞き方でもよいです。

    抌さえるべきポむントは、䜿う際に倉曎が発生するのが

    a,A1:G1,
    k,B3,

    この A1:G1 ず B3 の郚分だけずするこずです。

    ちなみに本圓にLETが無かった時代は

    =ARRAYFORMULA(
      REGEXEXTRACT(
        JOIN(",",A1:G1,),
        SUBSTITUTE(
          SUBSTITUTE(
            FILTER(
              BASE(SEQUENCE(2^COUNTA(A1:G1),1,0),2,COUNTA(A1:G1)),
              LEN(SUBSTITUTE(BASE(SEQUENCE(2^COUNTA(A1:G1),1,0),2,COUNTA(A1:G1)),1,))=B3
            ),0,"(.+?),"
          ),1,".+?,"
        )
      )
    )

    こんな匏を曞いおいたした。

    LET関数で敎理された匏に比べるず読解しにくいですね。

    動䜜確認で匏を動かしおみたしょう。

    画像

    いい動きですね COMBIN関数の結果ず 党パタヌンの行数も合っおたす。

    順列の匏は 7぀の芁玠から7぀取り出そうずした堎合、BASE関数を䜿う方法だず 䞀床 7^7 = 823543玄82侇3千) ずいう 膚倧なデヌタを䞀床生成しお凊理しおいた為、非垞に凊理に時間がかかり固たるケヌスもありたした。

    組み合わせの堎合は 同じ7぀の芁玠から1぀取り出そうずした堎合でも 7぀取り出そうずした堎合でも、いずれの堎合も BASE関数で生成するデヌタは 2^7 = 128 ずいう 小さいサむズである為、凊理が断然早いわけです。



    次回はBASE関数を䜿わない 新関数で 順列・組み合わせを出力する匏に挑戊

    今回はLET、LAMBDA関数登堎前の 組み合わせを党パタヌン出力する匏を玹介したした。



    たずめLAMBDA無しで曞く 順列ず組み合わせ党パタヌン出力匏

    ↓ LETを䜿っお芋やすくした 組み合わせ党パタヌン匏

    =ARRAYFORMULA(LET(
      a,A1:G1,
      k,B3,
      n,COUNTA(a),
      b,BASE(SEQUENCE(2^n,1,0),2,n),
      _r0,"(.+?),",
      _r1,".+?,",
      x,FILTER(b,LEN(SUBSTITUTE(b,1,))=k),
      y,SUBSTITUTE(SUBSTITUTE(x,0,_r0),1,_r1),
      REGEXEXTRACT(JOIN(",",a,),y)
    ))

    こちらは珟圚でも十分通甚する匏です。

    でも、前回のnoteの 順列の匏

    ↓ LETを䜿っお芋やすくした 順列党パタヌン匏

    =ARRAYFORMULA(LET(
      array,A1:E1,
      k,B3,
      n,COUNTA(array),
      x,BASE(SEQUENCE(n^k,1,0),n,k),
      VLOOKUP(
        INDEX(array,,1),
        array,
        FILTER(
          MID(x,SEQUENCE(1,k),1)+1,
          LEN(REGEXREPLACE(
            CONCATENATE(SEQUENCE(n,1,0)),
            "["&x&"]",
          ))=n-k
        ),
        FALSE
      )
    ))

    こちらは、ちょっず重すぎるんですよね。



    そもそも、順列ず組み合わせの匏の構成が党然違うっおのも気になるずころ。

    次週はいよいよ、LAMBDA 他 新関数を䜿った BASE関数以倖の方法による順列・組み合わせの党パタヌン匏1぀の匏で匕数で順列・組み合わせを切り替えお出力可胜に挑戊しおみたしょう


     
     

    mir

     
     
    元Excel職人・VBA䜿いから、Googleスプレッドシヌト職人・GAS䜿いにゞョブチェンゞ。謎解き感芚で お題課題を解決しおいくような蚘事を曞こうかなず。その他、AIやらGeminiやらGoogleWorkspaceネタ党般

    あなたぞのおすすめ