既定の関数では、1つの語句を置換するText.Replace()しか見当たらないようなので、まとめて複数語句を消したり、置換するコードを書いてみました。
2019/9/14追記:パターン2にもっと短いバージョンを書き加えました。
##サンプルデータ
詳細エディタに貼ってみてください。
let
Source = "H4sIAAAAAAAEAK2Wz09jVRTH9/xVFjOJrkxYaVyYTGbhwsRMDLp+p0anQEtLB5mNsfPSIC0Q6DQF+VEIpHR40hJHCYbYcXDMQAFJSnRhRhd+znnvta/VGBemeX333XvuOd/zPT/ulR+lIBUnJuE7JxdSl5JcicfXnKyIK2W5YW5ODlnVcZF3W1pSkaozzNsVT7b7pJupETlm/XAsh952oCvc30z/Isfp3zK/yhpfVVkUL/mBzIcah5xXFEb2Zd+mohNjW0M2mNljZU12eOp9ajooqAGhJatSV/nJnzF/7sQyL1C/n01K8d6l7DqxIWc0/m48Gx+NJ+Ij8dvxEScWf1PfNh4e+rdF50MFWJ9ZkH2YuJTazL0o9lEwP9cHjCWWm/JUHkGfWt9ipg5lPaKO8WgOieeybCQ9ZgcPo7xsy3HqcznFz9p4DD9mA9JfSD5EEeGULRuSn9hCsWvIcDv5AEoKjJ9JDfOd1BlArlBdR40hVloTWajDSKqNZB3z6g2UGtCufrSXlHj1MIf4NsifYuorM11g7pyvTShAbnA5x68VLoeyveUzWTIaS+KqQCjtC3gmsBMRUPoTjZ6bAO/gSrUXBuJPGuNyk5nq/xLvKK8RXhqZN+SYXBjIgz7mPHDrUwn3AyfjQHqkvLI36ffkO3xoy950UflIvybfD8a7TnxhwolpNOUbYumS4ss6o4UwPWc4d2yThzKluTH1iXjZPxUhyGctNr4P4ahgyVVjxpKOZGtHanHm7ek/ULavhsnTHa2sgVKnxrTYpXP/o+lEkK9+wPrKImCEvHxoAlU58x0bDeqlq9XGBcY32C1r0DPfmn03SFs2Mp+jso1HSCj2ZC1UpyRgB4PL1g20CwSmNqwotYMVUURMneFEldI8sApqdDcrk3nezZD8Ep/9SdDlQK5hYAV7XzNDkYDHw0Qx0iZRPXY02AgnDqZetwApg2U8nJeGhnbyjhYzOoLQwGTNL70TM/0I8cBdYNmWaIq4Ud5P+OW7zcj+gfOYkRotmZ5ei+rcjwehm1cFPmXq9awTiy5BzF5AY9Askg+zL+nQe5O3BqRWe2FGCdY8a+V9gkaQ4nOpdX2eUfmaVG6U/Qjj5mUQCWCf8uvMbNIJPGyuWapXUUKvx34xGO37rbB3QhD2CjFbUkjWLX7QWvTjkb2RXfHGPvYLx0/SBflJk6476h4Gt4xxTZij9Drx06IM86RAdri+M+kj/yybKI+/ipOLkP5k8v2wGQ8eH62ehZ7np30ZpF9PoHGROFSsMWgf6bYAxTLzJUzUohZa1l/Vj2uWtJy29RzgMHJlHcb1GMrrfYAz4e74F3poovTEohHz32EnYlS1atnyD1piSYNIvwO4Fu6Tm6m7lEWZaNLSEuuW5FW9L7CqAXT/i4d5YlBhg7U+zYTgmItcGOx0Yss1mGoRZUWZy06B4Bp8qzDb372L3Ht2wdxh/xWFduFLcF0os2PBv1CQrX7YOtO/y3zYbzXUpnnXArzWf/RgnQuHtP3EyWt9RMszSI1AbxO9rnF5ET1Z7FhrygHsLv1jgtC2rElZNlnjguwtPeD/Tmp94K7gkwihY+fSmSgkP6UH5MyPAJse8/Hb/ultb1SallOQXPntafJwMAgVu2gEHS29wuKlVA1V2E73zLimhZdNZrYevOWvfLZpVPYc/QvHXnlEmgoAAA==",
Custom1 = Binary.Decompress( Binary.FromText(Source),Compression.GZip),
Custom2 = Text.FromBinary(Custom1,932)
in
Custom2
##パターン1:指定した語句を全部抹消したい。
###消去対象のテキストのリスト
let
Source = "WyJcdTY4NDNcdTU5MmFcdTkwY2UiLCJcdTMwNGFcdTMwNThcdTMwNDRcdTMwNTVcdTMwOTMiLCJcdTMwNGFcdTMwNzBcdTMwNDJcdTMwNTVcdTMwOTMiLCJcdTY4NDMiXQ==",
Custom1 = Binary.FromText(Source),
#"Imported JSON" = Json.Document(Custom1,932)
in
#"Imported JSON"
###コード
= List.Accumulate(消去リスト,
サンプルテキスト,
(state,current)=>Text.Replace(state,current,"")
)
##パターン2:指定した表のとおり、置換したい。
あらかじめ変換表の形で用意しておいてから、それにしたがって、変換します。
###語句の変換表
let
Source = "H4sIAAAAAAAEAI2QOw6AIBAF70JtgSxfryIWuMINqIx3dxcrDRqbyf7ekDDvIlazlhyrRzuKiVrrNdAwqBRrkJjFQENXLN1Y2FZaFY/tEuSmmQWZON5Sx9Bxg9SJaXyrW9oYZoD3d5yC9O1zstXqn++Z6rv5H74cWV0Ux3IClZSxMUcBAAA=",
Custom1 = Binary.Decompress(Binary.FromText(Source),Compression.GZip),
#"Imported JSON" = Table.FromRecords(Json.Document(Custom1,932))
in
#"Imported JSON"
###コード(旧)
あとで取り出しやすいように、一度関数(fx_複数置換)を仕上げてから、実行させています。
[fx_複数置換=
(対象 as text,指示表 as table,C1 as text,C2 as text)=>
List.Last( List.Generate(()=>[id=0,vstr=対象],
each [id]<=Table.RowCount(指示表),
each [id=[id]+1,
vstr=Text.Replace([vstr],
Record.Field(指示表{[id]},C1),
Record.Field(指示表{[id]},C2)
)
],
each [vstr]
)
),
実行=fx_複数置換(サンプルテキスト,t_指示テーブル,"対象","置換後")
][実行]
###コード(新)
以前、コンペで考えたときに、もっと簡単な方法を思いついていましたが、載せるのを忘れてました。
たった、これだけです。
※空のクエリを作って、数式バーに貼ってください。
= List.Accumulate(
Table.ToRows(t_指示テーブル), //リストの各項目を用いた繰り返し処理。
サンプルテキスト, //初項。最初のxはこれになる。
(x,y)=>Text.Replace(x,y{0},y{1}) //{0},{1}はリストの項目の取り出し方の記法。
)
####Ver2の解説
みんな大好きList.Accumulate関数を使いました。
第一引数にあるリストの最初から、最後までの全項目を使って、何かやるときに使います。
公式の雪嶺ではstate,currentで関数を作ってますけど、要は順番と名前を間違えなければ、何でもいいんです。
※僕はxとyとか、aとbにすることが多いです。日本語で、「先」と「後」でもいいわけです。
List.Accumulate関数の進行の様子
x | y | 処理後の結果 | |
---|---|---|---|
1周目 | サンプルテキストの中身 | 桃太郎 | (桃太郎⇒ピーチ太郎置換後の文字列) |
2周目 | 1周目の処理後の結果 | おじいさん | (さらに、おじいさん⇒お爺置換後の文字列) |
3周目 | 2周目の処理後の結果 | おばあさん | (さらに、おばあさん⇒おばあ 置換後の文字列) |
4周目 | 3周目の処理後の結果 | 桃 | (さらに、桃⇒モモ置換後の文字列) |
公式の記事はこちら。(いずれも英語)
List.Accumulate - PowerQuery M | Microsoft Docs
Expressions, values, and let expression内のリストの箇所
List.Accumulate関数を本格的に使っている @PowerBIxyz さんの記事はこちら。
僕もこの記事を書いていただいてから、使い始めました。
Power Query の List.Accumulate 関数ってなんだよー - Qiita
##おまけ:パターン1別法
Splitter関数群にちょうどいいものがあるので、こちらの方がスッキリします。
ただ、僕は忘れそうだなと思ったので、Splitterを別法としました。
Text.Combine(
Splitter.SplitTextByEachDelimiter(消去リスト)(サンプルテキスト)
)
参考:レファレンス
Splitter.SplitTextByEachDelimiter | Microsoft Docs