Skip to content

Instantly share code, notes, and snippets.

@jlouis
Created November 15, 2016 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jlouis/525249cd5d7860d691cdd97b3a4845af to your computer and use it in GitHub Desktop.
Save jlouis/525249cd5d7860d691cdd97b3a4845af to your computer and use it in GitHub Desktop.
merge3
-module(z).
-export([t/0, merge/3]).
merge(F, L, R) ->
L1 = lists:sort(maps:to_list(L)),
L2 = lists:sort(maps:to_list(R)),
merge(F, L1, L2, []).
merge(_F, [], [], Acc) -> maps:from_list(Acc);
merge(F, [{KX, VX}|Xs], [], Acc) ->
merge(F, Xs, [], f(KX, F(KX, {left, VX}), Acc));
merge(F, [], [{KY, VY} | Ys], Acc) ->
merge(F, [], Ys, f(KY, F(KY, {right, VY}), Acc));
merge(F, [{KX, VX}|Xs] = Left, [{KY,VY}|Ys] = Right, Acc) ->
if
KX < KY -> merge(F, Xs, Right, f(KX, F(KX, {left, VX}), Acc));
KX > KY -> merge(F, Left, Ys, f(KY, F(KY, {right, VY}), Acc));
KX =:= KY -> merge(F, Xs, Ys, f(KX, F(KX, {both, VX, VY}), Acc))
end.
f(_K, undefined, Acc) -> Acc;
f(K, {ok, R}, Acc) -> [{K, R} | Acc].
t() ->
Map1 = #{ a => 1, b => 2 },
Map2 = #{ b => 3, c => 3 },
Fun1 = fun
(_K, {left, V}) -> {ok, V};
(_K, {right, V}) -> {ok, V};
(_K, {both, V1, V2}) -> {ok, V1 + V2}
end,
#{ a := 1, b := 5, c := 3 } = merge(Fun1, Map1, Map2),
Map3 = #{ a => #{ b => 2, f=> #{}} },
Map4 = #{ a=> #{b => 3, c => 4, d=> #{e=> 5}} },
Fun2 = fun
F(_K, {left, V}) -> {ok, V};
F(_K, {right, V}) -> {ok, V};
F(_K, {both, L, R}) when is_map(L), is_map(R) -> {ok, merge(F, L, R)};
F(_K, {both, L, R}) -> {ok, [L, R]} %% arbitrary choice
end,
#{a => #{b => [2,3],c => 4,d => #{e => 5},f => #{}}} =
merge(Fun2, Map3, Map4).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment