Want to learn?

Maps

Representation

Documentation

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]
0
iex> map["second"]
1
iex> map[{ :third }]
3
iex> map[:non_existing_key]
nil

There is a handy shortcut for atom-type keys:

iex> map.first
0

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]
nil
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"
}
Check our latest product - it's based on our experience of managing over 50-people strong company. The tool we're missing as a small company and not an enterprise.

humadroid.io is an employee and performance management software. It's an unique tool allowing everyone to be in the loop - by having up to date info about co-workers, time-off, benefits, assets, helping with one-on-ones, being a go-to place for company-wide announcements.

Check out humadroid.io
Top

Contact us

* Required fields

The controller of your personal data provided via this contact form is Prograils sp. z o.o., with a registered seat at Sczanieckiej 9A/10, 60-215 PoznaƄ. Your personal data will be processed in order to respond to your inquiries and for our marketing purposes (e.g. when you ask us for our post-development, maintenance or ad hoc engagements for your app). You have the rights to: access your personal data, rectify or erase your personal data, restrict the processing of your personal data, data portability and to object to the processing of your personal data. Learn more.

Notice

We do not track you online. We use only session cookies and anonymous identifiers for the purposes specified in the cookie policy. No third-party trackers.

I understand
Elo Mordo!Elo Mordo!