dictionary - 在地图中合并嵌套值的正确方法?
问题描述
鉴于以下情况:
M1 = #{ "Robert" => #{"Scott" => #{}} },
M2 = #{ "Robert" => #{"Adams" => #{}} }
合并应该是:
M3 = #{ "Robert" => #{ "Scott" => #{}, "Adams" => {}}
现在,如果我们合并以下内容:
M4 = #{ "William" => #{ "Robert" => #{ "Scott" => {} }}}
M5 = #{ "William" => #{ "Robert" => #{ "Fitzgerald" => {} }}}
我们应该得到以下信息:
M6 = #{ "Robert" => #{ "Scott" => #{}, "Adams" => {},
"William" => #{ "Robert" => #{ "Fitzgerald" => {}, "Scott" => {} }}}
我有迭代的想法,获取每个级别的键并迭代它们。检查它们是否相同,如果没有则合并地图,检查是否是地图,如果它没有停止并合并,否则再次调用自身。我遇到的问题是功能不断崩溃,有没有更好的方法来做到这一点?
这是我到目前为止的代码:
merger(M1, M2) ->
M1_Keys = maps:keys(M1),
M2_Keys = maps:keys(M2),
do_merge(M1, M2, M1_Keys).
do_merge(M1, M2, [Head|Tail]) ->
Check = check_if_same(M1, M2),
io:fwrite("Check is: ~p\n", [Check]),
case Check of
{ok, true} ->
io:fwrite("true\n");
{ok, false} ->
io:fwrite("false\n")
end,
do_merge(M1, M2, Tail);
% P1 = maps:get(Head, M1),
% P2 = maps:get(Head, M2),
% P3 = maps:merge(P1, P2),
% M4 = maps:update(Head, P3, M1),
% io:fwrite("~p \n", [M4]),
% do_merge(M1, M2, Tail);
do_merge(M1, M2, []) ->
ok.
check_if_same(M1, M2) ->
{ok, lists:sort( maps:keys(M1) ) == lists:sort( maps:keys(M2) )}.
但是,它崩溃并出现以下错误:
$erlc *.erl
helloworld.erl:10: Warning: variable 'M2_Keys' is unused
helloworld.erl:13: Warning: variable 'Head' is unused
helloworld.erl:30: Warning: variable 'M1' is unused
helloworld.erl:30: Warning: variable 'M2' is unused
$erl -noshell -s helloworld start -s init stop
Check is: {ok,true}
true
{"init terminating in do_boot",{{badmap,ok},[{maps,keys,[ok],[]},{helloworld,merger,2,[{file,"helloworld.erl"},{line,10}]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ()
Crash dump is being written to: erl_crash.dump...done
解决方案
你的do_merge
回报ok
总是(基本递归案例)。
在这里你有两个解决方案,第一个更具可读性,但我会选择第二个
deep_map_merge(M1, M2) when is_map(M1), is_map(M2) ->
% Merge both as if they had no common keys
FlatMerge = maps:merge(M1, M2),
% Get common keys (This is O(N^2), there are better ways)
CommonKeys = [K || K <- maps:keys(M1), K2 <- maps:keys(M2), K == K2],
% Update the merged map with the merge of the common keys
lists:foldl(fun(K, MergeAcc) ->
MergeAcc#{K => deep_map_merge(maps:get(K, M1), maps:get(K, M2))}
end, FlatMerge, CommonKeys);
deep_map_merge(_, Override) ->
Override.
deep_map_merge2(M1, M2) when is_map(M1), is_map(M2) ->
maps:fold(fun(K, V2, Acc) ->
case Acc of
#{K := V1} ->
Acc#{K => deep_map_merge2(V1, V2)};
_ ->
Acc#{K => V2}
end
end, M1, M2);
deep_map_merge2(_, Override) ->
Override.
推荐阅读
- arcgis-js-api - esri 将图形从 json 添加到图形层给出错误
- excel - 如何将 Match 的值设置为 vlookup 的范围
- vpn - 尝试通过 S2P Azure Vpn 访问计算资源时出现问题
- git - 我正在尝试将本地存储库附加到 github,但不能
- javascript - 如何使用 JS/JQ 复制 DOM 选择元素并保留所选选项
- .htaccess - htaccess url 重写和 https
- java - 将 Apache Common Math 3.6.1 项目从 Maven 存储库添加到 NetBeans 12.x 中的 Maven 项目
- r - 使用插入符号的交叉验证计算样本内预测准确性
- magento - 我在哪里可以找到 Magento 2 数据库中的客户 ID?
- react-native - React 本机 datepicker 插件在 Xcode 12 上构建 iOS 时抛出错误(“Property has a previous declaration”)