Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining two maps on same key in Elixir

Tags:

elixir

I'm pretty new to Elixir and just wanted to find what the best way is to combine two maps with on same key. To be more specific:

name_map = %{
  105 => "Jim",
  48 => "Maria",
  62 => "Karen",
  888 => "Foo"
}

job_map = %{
  105 => "Social worker",
  48 => "Programmer",
  62 => "Teacher",
  999 => "Bar"
}

and I am trying to get

combined_map = %{
  105 => %{"name" => "Jim", "job" => "Social worker"},
  48 => %{"name" => "Maria", "job" => "Programmer"},
  62 => %{"name" => "Karen", "job" => "Teacher"},
  888 => %{job: nil, name: "Foo"},
  999 => %{job: "Bar", name: nil}}
}

Thanks in advance for any help!

like image 577
phil Avatar asked Jun 01 '17 22:06

phil


2 Answers

A straightforward solution: get all the keys from the two maps, iterate over the keys, and retrieve values from the maps and construct the tuple {key, %{name: name, job: job}}, then reduce the tuples into a map.

name_map = %{
  105 => "Jim",
  48 => "Maria",
  62 => "Karen",
  888 => "Foo"
}

job_map = %{
  105 => "Social worker",
  48 => "Programmer",
  62 => "Teacher",
  999 => "Bar"
}

combined_map = Map.keys(name_map) ++ Map.keys(job_map)
               |> Stream.uniq
               |> Stream.map(&{&1, %{name: name_map[&1], job: job_map[&1]}})
               |> Enum.into(%{})

%{48 => %{job: "Programmer", name: "Maria"},
  62 => %{job: "Teacher", name: "Karen"},
  105 => %{job: "Social worker", name: "Jim"}, 
  888 => %{job: nil, name: "Foo"},
  999 => %{job: "Bar", name: nil}}
like image 114
Aetherus Avatar answered Oct 04 '22 20:10

Aetherus


Assuming that you have same keys in both maps, it’s fairly easy:

Map.merge(name_map, job_map, fn _k, v1, v2 ->
  %{name: v1, job: v2}
end)
#⇒ %{48 => %{job: "Programmer", name: "Maria"},
#    62 => %{job: "Teacher", name: "Karen"},
#   105 => %{job: "Social worker", name: "Jim"}}

Whether you want to support names without jobs and vice versa:

Enum.into(Map.keys(name_map) ++ Map.keys(job_map), %{}, fn k ->
  {k, %{name: Map.get(name_map, k), job: Map.get(job_map, k)}}
end)
#⇒ %{48 => %{job: "Programmer", name: "Maria"},
#    62 => %{job: "Teacher", name: "Karen"},
#   105 => %{job: "Social worker", name: "Jim"},
#   888 => %{job: nil, name: "Foo"},
#   999 => %{job: "Bar", name: nil}}
like image 35
Aleksei Matiushkin Avatar answered Oct 04 '22 22:10

Aleksei Matiushkin