Want to learn?




Maps are a key-value data structure where key and value can be represented by any type:

%{ :first_name => "User", :last_name => "Example", :age => 30 }

If the key is an atom, you can use the same shortcut that you use with keyword list:

%{ first_name: "User", last_name: "Example", age: 30 }

The use of a map is similar to the keyword list since it also represents values by keys. However, there are some differences:

  • You can not duplicate keys, because if you do, only the last key-value occurrence will be used:

    iex> %{ x: 10, x: 15 }
    %{x: 15}
  • Elements of map are not ordered, which is also different to keyword list:

    iex> %{last_name: 'Example', first_name: 'User'}
    %{first_name: 'User', last_name: 'Example'}
  • Inserting new elements to a map might be slower than in case of keyword list since the second one (in best case scenario) is just prepending a new element to the beginning of a list.

  • Accessing elements is much faster when using map (constant time access), since keyword list need to iterate over its elements.

  • A map is used to store actual payload data since they have a hash-based implementation.

Accessing map elements

You can access map elements with square-bracket syntax:

iex> map = %{ :first => 0, "second" => 1, { :third } => 3 }
%{:first => 0, {:third} => 3, "second" => 1}
iex> map[:first]
iex> map["second"]
iex> map[{ :third }]
iex> map[:non_existing_key]

There is a handy shortcut for atom-type keys:

iex> map.first

When there is no match you get a KeyError:

iex> map.non_existing_key
** (KeyError) key :non_existing_key not found in: %{:first => 0, {:third} => 3, "second" => 1}

Notice the difference between . and [] syntax when accessing a non-existing element:

iex(5)> map[:non_existing_key]
iex(6)> map.non_existing_key
** (KeyError) key :non_existing_key not found in: %{:first => 0, {:third} => 3, "second" => 1}

Updating map elements

Elixir has a very handy syntax for updating values of a given keys in map:

iex> person = %{ first_name: "User", last_name: "Example" }
%{first_name: "User", last_name: "Example"}
iex> person = %{ person | first_name: "Michael", last_name: "Johnson" }
%{first_name: "Michael", last_name: "Johnson"}
iex> person = %{ person | age: 23 }
** (KeyError) key :age not found in: %{first_name: "User", last_name: "Johnson"}
    (stdlib) :maps.update(:age, 23, %{first_name: "User", last_name: "Johnson"})
    (stdlib) erl_eval.erl:259: anonymous fn/2 in :erl_eval.expr/5
    (stdlib) lists.erl:1263: :lists.foldl/3

As you can see you can use the following syntax to update a value of key:

map_variable = %{ map_variable | key-value pairs }

There are also two things worth to mention:

  • you can specify multiple key-value pairs,

  • you can't modify a value of non-existing key.

Nested maps

Maps can be nested:

iex> person = %{ first_name: "User", last_name: "Example", address: %{ city: "New York", country: "USA", street: "Wall St" } }
  address: %{city: "New York", country: "USA", street: "Wall St"},
  first_name: "User",
  last_name: "Example"

You can easily access nested data with [] or . (when dealing with atoms) operator:

iex> person[:address][:city]
"New York"
iex> person.address.city
"New York"

Update is not so obvious, you can't just simply assign new value this way:

iex> person.address.city = "Washington"
** (CompileError) iex:4: cannot invoke remote function person.address/0 inside match

Instead, you should use following syntax:

iex> person = put_in person[:address][:city], "Washington"
  address: %{city: "Washington", country: "USA", street: "Wall St"},
  first_name: "User",
  last_name: "Example"

It not only works for updating data, but also for putting new ones:

iex> person = put_in person[:address][:number], 1
  address: %{city: "Washington", country: "USA", number: 1, street: "Wall St"},
  first_name: "User",
  last_name: "Example"

You can delete given key with pop_in/2 function:

iex(4)> {_, person} = pop_in(person, [:address, :street])
{"Wall St",
   address: %{city: "New York", country: "USA"},
   first_name: "User",
   last_name: "Example"
iex(5)> person
  address: %{city: "New York", country: "USA"},
  first_name: "User",
  last_name: "Example"

Start a project with your dedicated software house


Contact us

* Required fields

Elo Mordo!Elo Mordo!