fukuoka.ex代表のpiacereです
今回もご覧いただいて、ありがとうございます
Elixirで関数を書いていると、Enum.drop()のような、複数キーが指定可能な処理をサクっと書きたいシチュエーションがあります
単独キーの関数を、複数キー対応することで、このコツのようなものをシェアしたいと思います
関数サンプル:マップリストを単独キー指定で文字列置換
マップリストのマップにある値を、単独キー指定で文字列置換する関数を以下のように書いてみます
defmodule MapList do
@doc """
Replace map value
## Examples
iex> MapList.replace( [ %{ "c1" => "v1", "c2" => "v2" }, %{ "c1" => "v3", "c2" => "v4" } ], "c1", "v", "Value" )
[ %{ "c1" => "Value1", "c2" => "v2" }, %{ "c1" => "Value3", "c2" => "v4" } ]
"""
def replace( map_list, column, pattern, replacement ) do
map_list |> Enum.map( fn item_map -> Map.put( item_map, column, String.replace( item_map[ column ], pattern, replacement ) ) end )
end
end
マップリストを複数キー指定で文字列置換
上記関数を複数キー対応すると、以下のようになります
defmodule MapList do
@doc """
Replace map values
## Examples
iex> MapList.replace( [ %{ "c1" => "v1", "c2" => "v2" }, %{ "c1" => "v3", "c2" => "v4" } ], [ "c1" ], "v", "Value" )
[ %{ "c1" => "Value1", "c2" => "v2" }, %{ "c1" => "Value3", "c2" => "v4" } ]
iex> MapList.replace( [ %{ "c1" => "v1", "c2" => "v2" }, %{ "c1" => "v3", "c2" => "v4" } ], [ "c1", "c2" ], "v", "Value" )
[ %{ "c1" => "Value1", "c2" => "Value2" }, %{ "c1" => "Value3", "c2" => "Value4" } ]
"""
def replace( map_list, columns, pattern, replacement ) do
columns
|> Enum.reduce( map_list, fn column, acc ->
acc |> Enum.map( fn item_map -> Map.put( item_map, column, String.replace( item_map[ column ], pattern, replacement ) ) end )
end )
end
end
ポイントは、以下5点です
- 第2引数を、複数キー指定可能とするため、リストに変更した
- 複数キーでEnum.reduce()を回すことで、キーの個数分、処理を繰り返すようにした
- Enum.reduce()の初期値をmap_listとし、それをaccとして、各キーの更新を反映させた
- マップ内で行う置換処理は、変更前と変えていない(パイプの前がmap_listからaccに変わっただけ)
- 複数キーのテストケースを追加した ※実際はTDDしているので、先にテストから変更した
「Enum.reduce()がちょっと慣れなくて苦手」という方は、「accの初期値はmap_list」という点と、「accが繰り返し更新される」という点に着目すると、少し読みやすくなるかも知れません
p.s.「いいね」よろしくお願いします
ページ左上の や のクリックを、どうぞよろしくお願いします
ここの数字が増えると、書き手としては「ウケている」という感覚が得られ、連載を更に進化させていくモチベーションになりますので、もっとElixirネタを見たいというあなた、私達と一緒に盛り上げてください!