🎓 A1Learner
🔍
0 of 54 lessons completed

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?