在Elixir中将相同键上的两个映射组合在一起

时间:2017-06-01 22:44:26

标签: elixir

我对Elixir很新,只是想找到将两张地图与同一把钥匙组合起来的最佳方法。更具体一点:

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

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

我想要

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}}
}

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:6)

一个简单的解决方案:从两个映射中获取所有键,迭代键,从映射中检索值并构造元组{key, %{name: name, job: job}},然后将元组缩减为映射。

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}}

答案 1 :(得分:3)

假设两张地图都有相同的按键,那就相当容易了:

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"}}

是否要支持没有工作的名称,反之亦然:

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}}

答案 2 :(得分:1)

将每个地图转换为jobname键下方的值,然后Map.merge以合并条目。

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

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

Map.merge(
  Enum.into(name_map, %{}, fn {k, v} -> {k, %{name: v}} end), 
  Enum.into(job_map, %{}, fn {k, v} -> {k, %{job: v}} end), 
  fn _k, v1, v2 -> Map.merge(v1, v2) end)

%{48 => %{job: "Programmer", name: "Maria"},
  62 => %{job: "Teacher", name: "Karen"},
  105 => %{job: "Social worker", name: "Jim"}}