Elixir Nested Data
Nested data is a map that holds other maps inside it. A path of keys leads from the outer map down to one inner value.
Read a value deep inside a map
get_in follows the path one key at a time. The path [:address, :city] ends at the inner city value.
user = %{name: "Ana", address: %{city: "Oslo", zip: "0150"}}
IO.puts(get_in(user, [:address, :city]))
IO.puts(get_in(user, [:name]))Set a nested value with put_in
put_in returns a whole new structure with the nested value set. Reading both maps back shows the original still holds the old city.
user = %{name: "Ana", address: %{city: "Oslo", zip: "0150"}}
moved = put_in(user, [:address, :city], "Bergen")
IO.puts(get_in(moved, [:address, :city]))
IO.puts(get_in(user, [:address, :city]))Transform a nested value with update_in
update_in passes the current nested value to a function. Here the function adds one to the login count.
user = %{name: "Ana", stats: %{logins: 3}}
updated = update_in(user, [:stats, :logins], fn n -> n + 1 end)
IO.inspect(updated)
IO.puts(get_in(updated, [:stats, :logins]))Example
profile = %{name: "Ana", address: %{city: "Oslo", zip: "0150"}, visits: %{count: 2}}
IO.puts(get_in(profile, [:address, :city]))
moved = put_in(profile, [:address, :city], "Bergen")
visited = update_in(moved, [:visits, :count], fn n -> n + 1 end)
IO.puts(get_in(visited, [:address, :city]))
IO.puts(get_in(visited, [:visits, :count]))Key points
- Path: A path is a list of keys, such as [:address, :city], that leads into nested maps.
- get_in: get_in(data, path) reads the value at the end of the path.
- put_in: put_in(data, path, value) returns a new structure with the value at the path replaced.
- update_in: update_in(data, path, fun) returns a new structure where a function transforms the value at the path.
- Atom keys: The paths in this lesson use atom keys on plain maps.
In this example, get_in reads the city from the nested address map. put_in builds a copy with a new city, update_in raises the nested visit count in that copy, and the last two lines read the new city and count back.
Note
put_in and update_in return new structures and the original nested data stays unchanged.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does get_in(%{a: %{b: 7}}, [:a, :b]) return?