给出两个可能的输入:
a = %{ inner: %{hello: :world}}
OR
a = %{}
我想将b = %{foo: :bar}
合并到地图中以生成:
%{inner: %{foo: :bar}}
或
%{inner: %{hello: :world, foo: :bar}}
在第二个。
我可以用
解决它merged = Map.get(a, :inner, %{})
|> Map.merge(b)
put_in(a, [:inner], merged)
但是有更好的内置方式吗?我认为深度合并应该比这更容易。
答案 0 :(得分:1)
我认为您正在寻找Map.merge/3功能。第三个参数是一个解决冲突的函数:
a = %{inner: %{hello: :world}}
b = %{foo: :bar}
Map.merge(a, %{inner: b}, fn _, m1, m2 -> Map.merge(m1, m2) end)
因此,在这种情况下,当发生冲突时(两个正在合并的映射具有相同的密钥),将调用所提供的函数。当a
为%{}
时,不会发生冲突并返回%{inner: %{foo: :bar}}
。
答案 1 :(得分:1)
您可以使用update_in/3
+ Access.key/2
:
iex(1)> a1 = %{ inner: %{hello: :world}}
%{inner: %{hello: :world}}
iex(2)> a2 = %{}
%{}
iex(3)> b = %{foo: :bar}
%{foo: :bar}
iex(4)> update_in(a1, [Access.key(:inner, %{})], &Map.merge(&1, b))
%{inner: %{foo: :bar, hello: :world}}
iex(5)> update_in(a2, [Access.key(:inner, %{})], &Map.merge(&1, b))
%{inner: %{foo: :bar}}