Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Maps and Keyword Lists

03-maps-and-keyword-lists.livemd

Maps and Keyword Lists

Maps

We can define maps with following syntax

%{ "key1" => "value1", key2: :value2, key3: [] }

Accessing elements in a map

Lets define a map first to store user data

user = %{
  :name => "Kasun",
  "company" => "WaveZync ๐ŸŒŠ",
  :hobbies => ["Watching Anime", "Workouts", "Movies"]
}

Lets access elements

If the key is an atom we can access it with dot syntax

user.name
user.hobbies

If not it will give an error

user.company

To access keys which are not atoms we can use following syntax

user["company"]

It can be any key so even this is valid too

user_data = %{ 1 => "hello", 2 => :bello, :minion => "Kevin" }
user_data[1]
user_data[2]
user_data[:minion]

Updating a map

user = %{
  :name => "Kasun",
  "company" => "WaveZync ๐ŸŒŠ",
  :hobbies => ["Watching Anime", "Workouts", "Movies"]
}

If the key is pre-defined, we can update it with following syntax

%{ user | "company" => "Its still WaveZync ๐Ÿ˜’" }

if the Key is not there, it will scream ๐Ÿ™€

%{ user | :nickname => "kasvith" }

There are macros provided by the Elixir to work with maps like put_in/2, update_in/2

Lets update the user to add few more hobbies

user = update_in user.hobbies, fn hobbies -> ["Music" | hobbies] end

Lets change the name also

user = put_in user.name, "Kasun Vithanage"

There are lot of other ways to interact with maps, you can find them in docs

There is also Map module which contains lot of useful methods

Lets see how we can use it to get a value from a map and fallback to a default value if key is not present

Map.get(user, :name)
Map.get(user, :age) # see this doesnt scream
Map.get(user, :age, 29)

Keyword Lists

We can create a keyword list simply by using atoms a keys

spell = [
  name: "Arcane Blast",
  power_level: 9000,
  cast_time: 3.5,
  cooldown: 10,
  elements: [:fire, :lightning],
  mana_cost: 50,
  effects: [
    damage: 150,
    burn: 30,
    stun: 2
  ],
  description: "Unleash a powerful arcane blast that sears enemies with fire and lightning."
]

We can actually define it like follows as well

Once evaluated you will see it will be similar to above output

[{:hello, "world"}, {:bye, "world"}]

A practical usage can be find in String.split/2 function where we need to pass additional arguments to the function

> This is similar to kwargs in python for example

String.split("1 2      3", " ")

With trimming

String.split("1 2        3", " ", [trim: true])

We can write it as follows also without the brackets

String.split("1 2        3", " ", trim: true)

This is really useful when building queries with Ecto

query =
  from u in User,
    where: u.age > 18,
    where: u.age < 40,
    select: u

Keyword List manipulation

Same as Map you can use Keyword module to deal with Keyword Lists

Keyword.get(spell, :name)
Keyword.get(spell, :wizard)