こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はマップリストの要素を検索する方法を学びましたのでまとめます。
目次
1.Ectoスキーマからパターンマッチを使用してパラメータを取り出す
2.Ectoスキーマからパラメータを取り出して更新する(iex内のみ)
3.Enum.mapの紹介
4.Enum.filterの紹介
5.String.contains?の紹介
6.Enum.intoの紹介
7.Map.putの紹介
8.(番外編)元データがマップ→リスト→マップのもう一段深い入れ子構造だったらどうするか?(Map.getの紹介)(本記事)
目的
リストの要素がマップ(あるいはその逆)になっている場合に値を取り出して操作できるようになりたい。
実行環境
Windows 11 + WSL2 + Ubuntu 22.04
Elixir v1.14.3
Erlang v26.0.2
Phoenix v1.7.10
今回やりたいこと
前回までは元データが「リストの要素がマップ」という構造でした。
今回は番外編として元データがマップ→リスト→マップのもう一段深い入れ子構造だったらどうするか?を考えます。
例として、ページネーションコンポーネントであるScrivenerを導入した場合のデータ構造を考えてみます。
Scrivenerの導入
実施手順はこちらで別記事化しています。
元データ
マップ→リスト→マップの形をしていて、前回よりもう一段深い入れ子構造になっています。
iex(1)> users2 = Nov11.Users.list_users()
%Scrivener.Page{
page_number: 1,
page_size: 5,
total_entries: 23,
total_pages: 5,
entries: [
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
name: "hogehoge",
age: 10,
inserted_at: ~U[2023-11-11 14:34:43Z],
updated_at: ~U[2023-11-11 14:34:43Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 4,
name: "hogefuga",
age: 20,
inserted_at: ~U[2023-12-06 00:15:28Z],
updated_at: ~U[2023-12-11 14:12:04Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 5,
name: "piyopiyo",
age: 30,
inserted_at: ~U[2023-12-06 00:15:35Z],
updated_at: ~U[2023-12-06 00:15:35Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 6,
name: "user1",
age: 11,
inserted_at: ~U[2023-12-17 11:00:36Z],
updated_at: ~U[2023-12-17 11:00:36Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 7,
name: "user2",
age: 12,
inserted_at: ~U[2023-12-17 11:00:36Z],
updated_at: ~U[2023-12-17 11:00:36Z]
}
]
}
Map.getとは
第一引数のマップに対して第二引数のキーで検索し、ヒットした場合キーに対応する値を出力する。
users2 |> Map.get(:entries)
[
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
name: "hogehoge",
age: 10,
inserted_at: ~U[2023-11-11 14:34:43Z],
updated_at: ~U[2023-11-11 14:34:43Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 4,
name: "hogefuga",
age: 20,
inserted_at: ~U[2023-12-06 00:15:28Z],
updated_at: ~U[2023-12-11 14:12:04Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 5,
name: "piyopiyo",
age: 30,
inserted_at: ~U[2023-12-06 00:15:35Z],
updated_at: ~U[2023-12-06 00:15:35Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 6,
name: "user1",
age: 11,
inserted_at: ~U[2023-12-17 11:00:36Z],
updated_at: ~U[2023-12-17 11:00:36Z]
},
%Nov11.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 7,
name: "user2",
age: 12,
inserted_at: ~U[2023-12-17 11:00:36Z],
updated_at: ~U[2023-12-17 11:00:36Z]
}
]
入れ子構造が一段階浅くなり、③ -Enum.mapの紹介の元データと同じ「リストの要素がマップ」の構造になりました。
後はEnum.mapを使って、欲しい要素を取り出して、データ変換・更新色々できます。
例
users2
|> Map.get(:entries)
|> Enum.map(fn user -> user.name end)
["hogehoge", "hogefuga", "piyopiyo", "user1", "user2"]
users2
|> Map.get(:entries)
|> Enum.map(fn user -> user.name end)
|> List.first()
"hogehoge"
users2
|> Map.get(:entries)
|> Enum.map(fn user -> user.name end)
|> List.first()
|> String.length()
8
まとめ
- リストの要素がマップの場合はEnum.map
- マップの要素がリストの場合はMap.get
をそれぞれ使えば入れ子を解消できることを学びました(^▽^)/
~Elixirの国のご案内~
↓Elixirって何ぞや?と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます
↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ!私もエンジニア未経験から学習中です。
↓We Are The Alchemists, my friends!1
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。2
-
@torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。 ↩