26
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ときおり出てくる "each" キーワードと "_" (アンダースコア) とは

Posted at

Power BI Desktop や Excel のクエリ エディターでデータの変換や加工をしていると、"each" キーワードと "_"(アンダースコア)が 式に使用されている。さて、これは何か?というお話。クエリ エディターで生成された Power Query(M言語)を理解し、もっと複雑な処理(適用するステップ)をしたい場合には必要なことなので。

ボタンポチポチだけの作業で済むのなら気にすることはないけれども。

どのように使われているか

例えば、Table.AddColumn 関数 - Power Query M function reference

構文:Table.AddColumn(M)
Table.AddColumn(
    table as table,
    newColumnName as text,
    columnGenerator as function, // <--- ここで使用されている
    optional columnType as nullable type
) as table

テーブルに列を追加するとき、その追加列の値を 関数型( type function )の引数 : columnGenerator で指定している。

"テーブル" に対し "追加列" という列を追加し、その値をそれぞれ 0 にするというステップでは、"each" がでてくる。
image.png

列の追加(テーブル)
Table.AddColumn( テーブル, "追加列", each 0 )

テーブル から空白行を除外するステップを適用するとき、"each" と "_"(アンダースコア) が使われている。

空白行の削除(テーブル)
Table.SelectRows(
    PreviousStep_table,
    each not List.IsEmpty(
        List.RemoveMatchingItems(
            Record.FieldValues(_),
            {"", null}
        )
    )
)

"each" キーワード と "_"(アンダースコア)

"each" と "_"(アンダースコア) はセットで使用するが、"_"(アンダースコア) は省略されることがある。

each

そのまんまの意味で each です。"それぞれ" と考えてよさそう。

  • リスト(list)を扱う関数の場合、リストのアイテム(item)それぞれに処理を行う
  • テーブル(table)を扱う関数の場合、行(row)それぞれに処理を行う

"_"(アンダースコア)

リスト ( list )

リストアイテムそれぞれに加算(+1)
List.Transform( {1, 2, 3}, each _ + 1 ) = {2, 3, 4} // true
構文:List.Transform(M)
List.Transform(
    list as list,
    transform as function
)  as list

each _ + 1 の "_"(アンダースコア)は、リストアイテムそれぞれを処理するときそのアイテムを表す変数名。

テーブル ( table )

テーブルから特定の列を除外
Table.SelectRows( テーブル , each [列1] > 3)
構文:Table.SelectRows(M)
Table.SelectRows(
    table as table,
    condition as function
) as table

ここには "_"(アンダースコア)がない。これは速記簡略されていると考えればよくて、

テーブルから特定の列を除外
Table.SelectRows( テーブル , each _[列1] > 3 )

each _[列1] > 3 の "_"(アンダースコア)は、テーブル各行でそれぞれを処理するときその行を表す変数名。
そして、そのデータ型は record に特定。なので、フィールドをルックアップする記述は、"[ ]"(ブラケット)を使って _[ column-name ]

取りうる値はレコード型
let
    Source = #table(
        type table [列1 = any, 列2 = any],
        {
            {"A", 1}, {"A", 2}, {"B", 3}, {"B", 4}
        }
    ),
    AddedCustom = Table.AddColumn(
        Source,
        "IsType.Record",
        each Type.Is( Value.Type( _ ), Record.Type ) )
in
    AddedCustom

image.png

shorthand

Power Query での関数の記述は、(x) => x + 10 という感じなのだけど、テーブルやリスト扱う関数では 速記簡略する記述が可能なことが多い。そして中の人は多く使っている。

極端な例
let
    Source = #table(
        type table [列1 = any, 列2 = any],
        {
            {"A", 1}, {"A", 2}, {"B", 3}, {"B", 4}
        }
    ),
    TrimmedText = Table.TransformColumns( Source, { "列1", Text.Trim } ) // ココ、トッテモ shorthand
in
    TrimmedText

変換対象の値がひとつに特定でき、かつ、変換関数の必須引数がひとつなのでとてもシンプルな記述になっているわけで、
Table.TransformColumns( Source, { "列1", each Text.Trim( _ ) } )
とも記述できるし、
Table.TransformColumns( Source, { "列1", ( CurrentString ) => Text.Trim( CurrentString ) } )
とも記述できる。

変換関数の必須の引数が複数になるときや、オプション引数にも値を渡す場合には、"each" キーワード と "_"(アンダースコア) を使用することになるんですけど。

その他

26
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?