こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はマップリストのデータの操作についてEnumチートシートを写経して学んだことをまとめます。
本記事はmapping(関連付けする関数群)についてです。
目的
マップリストの値の操作ができるように様々な関数を知りたい。
実行環境
Windows 11 + WSL2 + Ubuntu 22.04
Elixir v1.14.3
Erlang v26.0.2
前提
本シリーズは下記でscaffold生成されたPhoenix+LiveViewのプロジェクトを使用しています。
mix phx.new dec23
cd dec23
mix ecto.create
mix phx.gen.live Users User users name:string age:integer
# 生成されたroutingをrouter.exに記載
mix ecto.migrate
元データ
iex(1)> users = Dec23.Users.list_users
[debug] QUERY OK source="users" db=1.7ms idle=1572.5ms
SELECT u0."id", u0."name", u0."age", u0."inserted_at", u0."updated_at" FROM "users" AS u0 []
↳ :erl_eval.do_apply/7, at: erl_eval.erl:746
[
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
name: "santa",
age: 100,
inserted_at: ~U[2023-12-23 09:06:44Z],
updated_at: ~U[2023-12-23 09:06:44Z]
},
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 2,
name: "reindeer",
age: 55,
inserted_at: ~U[2023-12-23 09:07:18Z],
updated_at: ~U[2023-12-23 09:07:18Z]
},
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 3,
name: "dwarf",
age: 39,
inserted_at: ~U[2023-12-23 09:07:44Z],
updated_at: ~U[2023-12-23 09:07:44Z]
}
]
Enumチートシートとは?
Enumチートシートというものがあります。
下記のマップリストを例にしたチートシートです。
幸運なことに元データと同じデータ構造をしています!
cart = [
%{fruit: "apple", count: 3},
%{fruit: "banana", count: 1},
%{fruit: "orange", count: 6}
]
というわけでこれを写経してみました。
Enum.map
第一引数の要素を順番に取り出す。
取り出した各要素に第二引数の関数処理をする。
お手本の写経
Enum.map(cart, & &1.fruit)
["apple", "banana", "orange"]
Enum.map(cart, fn item ->
%{item | count: item.count + 10}
end)
[%{count: 13, fruit: "apple"}, %{count: 11, fruit: "banana"}, %{count: 16, fruit: "orange"}]
自分のケースでの演習
Enum.map(users, & &1.name)
["santa", "reindeer", "dwarf"]
users
|> Enum.map(fn user -> %{user | age: user.age + 10} end)
[
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
name: "santa",
age: 110, #10歳増えた
inserted_at: ~U[2023-12-23 09:06:44Z],
updated_at: ~U[2023-12-23 09:06:44Z]
},
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 2,
name: "reindeer",
age: 65, #10歳増えた
inserted_at: ~U[2023-12-23 09:07:18Z],
updated_at: ~U[2023-12-23 09:07:18Z]
},
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 3,
name: "dwarf",
age: 49, #10歳増えた
inserted_at: ~U[2023-12-23 09:07:44Z],
updated_at: ~U[2023-12-23 09:07:44Z]
}
]
Enum.map_every
第一引数に0ベースでインデックスを振る。
第一引数の要素を順番に取り出す。
取り出した各要素のうち、インデックスが第二引数の倍数ごとに、要素に対して第三引数の関数処理をする。1
但し最初の要素は必ず関数処理をする。
お手本の写経
Enum.map_every(cart, 2, fn item ->
%{item | count: item.count + 10}
end)
[%{count: 13, fruit: "apple"}, %{count: 1, fruit: "banana"}, %{count: 16, fruit: "orange"}]
Enum.map_every(1..10, 3, fn x -> x + 1000 end)
[1001, 2, 3, 1004, 5, 6, 1007, 8, 9, 1010] #最初の要素と3の倍数のインデックスに対して関数処理をしている
自分のケースでの演習
iex(34)> Enum.map_every(users, 2, fn user -> %{user | age: user.age + 10} end)
[
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
name: "santa",
age: 110, #最初の要素は必ず関数処理をする
inserted_at: ~U[2023-12-23 09:06:44Z],
updated_at: ~U[2023-12-23 09:06:44Z]
},
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 2,
name: "reindeer",
age: 55,
inserted_at: ~U[2023-12-23 09:07:18Z],
updated_at: ~U[2023-12-23 09:07:18Z]
},
%Dec23.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 3,
name: "dwarf",
age: 49, #0ベースインデックスで2番目の要素なので関数処理をする
inserted_at: ~U[2023-12-23 09:07:44Z],
updated_at: ~U[2023-12-23 09:07:44Z]
}
]
内包表記(for文)
<- の右側の要素を順番に取り出す。
取り出した各要素にdo endブロック内の処理をする。
お手本の写経
for item <- cart do
item.fruit
end
["apple", "banana", "orange"]
自分のケースでの演習
for user <- users do
user.name
end
["santa", "reindeer", "dwarf"]
内包表記(for文)とfilteringの合わせ技
<- の右側の要素を順番に取り出す。
do
の前に書かれた条件にヒットした要素にのみ絞り込み、do endブロック内の処理をする。
お手本の写経
for item <- cart, item.fruit =~ "e" do
item.fruit
end
["apple", "orange"]
自分のケースでの演習
for user <- users, user.name =~ "a" do
user.name
end
["santa", "dwarf"]
~Elixirの国のご案内~
↓Elixirって何ぞや?と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます
↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ!私もエンジニア未経験から学習中です。
↓We Are The Alchemists, my friends!2
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。3
-
世界のナベアツ的なイメージ?インデックスが3だったら、要素が3つ飛びに関数処理が入るイメージ。1,2,「サン!」, 4, 5, 「ロク!」みたいな?(ネタが古い(;'∀')) ↩
-
@torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。 ↩