Power BI Desktop や Excel 利用できる Power Query で list がもっとうまく使えたらなぁと最近よく思うんです。繰り返したい処理とかでも使えそうですし。そう思った事の発端は、
- Using List.Generate() To Make Multiple Replacements Of Words In Text In Power Query
- Nested Loop with List.Generate in Power Query
とかで MSDN:List.Generate を調べていたからなんだけど、ここまで複雑なことでなくても list を扱えれば便利じゃないかなと考えた次第。よく使う Power Query の関数なかでも引数の型が list なのもそこそこありますしね。
クエリ エディターでの作業の多くは Table に対してのことが多いのだけど、あれこれしているうちに、これって列の追加や値の変換とかでは解決できないんじゃね?とか手詰まりに近いことあったりするんですね。複雑な処理はユーザー定義関数を用意したりして工夫をしたりはするけれども。で、List.Generate を使って何かを解決する前に List と関連する関数にちょっと注目してみた。
List は { } で表現
簡単なところから。{1, 2, 3}は、すべてのリストアイテムが数値(number)の List。
{1, "A", 3} { {1, "A"}, {2, "B"} }リストアイテムは型は any で特定されなくてもよいのでネストしたりしても可。型が record や table というのもよく見かけることになるかもしれない。
{1, 2, 3} = {1, 2, 3} // true {1, 2, 3} <> {1, 3, 2} // true {10, 20, 20} = {10, 20, 10 + 10 } // true {"A", "B"} & {"C"} = {"A", "B", "C"} // true重要なのはアイテムの順番ですね。ほか便利な記法としてはシーケンサ(..)というの使えます。ただし、値や文字コードが昇順になっていないとリストアイテム数が 0 の List になってしまいます。
{1 .. 5} = {1, 2, 3, 4, 5} // true {"A" .. "C"} = {"A", "B", "C"} // true List.Count({3 .. 1}) = 0 // trueリストアイテムを参照する { } と間違いのないように。
{"A", "B", "C"}{1} = "B" // true
便利そうなので使ってみた組合せ
Text.ToList:文字列を list に変換Text.Combine:アイテム(text)の list からひとつの文字列に結合
List.ToList("ABCDE") = {"A", "B", "C", "D", "E"} // true Text.Combine({"A", "B", "C", "D", "E"}) = "ABCDE" // true文字列を list に変換 → すべてのアイテム(text)に対し List.Transform などで処理 → 再び結合すれば置換のような処理になる。単純な置換であれば、List.ReplaceMatchingItems でよいかな。
List.ReplaceMatchingItems({"A", "B", "C"}, {{"A", 1}, {"C", 3}}) = {1, "B", 3} // trueリストアイテムにマッチするものを置換してくれるのだけど、引数がリスト{OldText, NewText}のリストだから、
Text.Combine( List.ReplaceMatchingItems( Text.ToList( "平成29年6月15日" ), List.Zip( {{"0".."9"}, {"0".."9"}} ) ) ) = "平成29年6月15日" // trueという感じに表現できてよいかも。
もう少し範囲を拡げて 全角英数記号などを半角に変換するならこんな感じでも。
(Source as text) as text => let Combi = List.Zip( { {Character.FromNumber(0x3000), "!".."~"}, {Character.FromNumber(0x20), "!".."~"} } ), TextList = List.ReplaceMatchingItems(Text.ToList(Source), Combi) in Text.Combine(TextList)