mirror of
https://github.com/valitydev/genlib.git
synced 2024-11-06 01:05:20 +00:00
feat: Add map:zipfold (#37)
This commit is contained in:
parent
b08ef4d61e
commit
82c5ff3866
@ -19,6 +19,7 @@
|
||||
-export([diff/2]).
|
||||
-export([fold_while/3]).
|
||||
-export([search/2]).
|
||||
-export([zipfold/4]).
|
||||
|
||||
%%
|
||||
|
||||
@ -176,3 +177,25 @@ do_search(Fun, {Key, Value, Iter}) ->
|
||||
true -> {Key, Value};
|
||||
false -> do_search(Fun, maps:next(Iter))
|
||||
end.
|
||||
|
||||
%% @doc Fold two maps "joining" them by key.
|
||||
%% NOTE: If a key-value exists only in one map, this pair is ignored altogether
|
||||
-spec zipfold(
|
||||
fun((K, V1, V2, A) -> A),
|
||||
InitAcc :: A,
|
||||
#{K => V1},
|
||||
#{K => V2}
|
||||
) -> A.
|
||||
zipfold(Fun, Acc, M1, M2) ->
|
||||
maps:fold(
|
||||
fun(Key, V1, AccIn) ->
|
||||
case maps:find(Key, M2) of
|
||||
{ok, V2} ->
|
||||
Fun(Key, V1, V2, AccIn);
|
||||
error ->
|
||||
AccIn
|
||||
end
|
||||
end,
|
||||
Acc,
|
||||
M1
|
||||
).
|
||||
|
@ -57,6 +57,63 @@ prop_search_not_found() ->
|
||||
end
|
||||
).
|
||||
|
||||
-spec prop_zipfold() -> proper:test().
|
||||
prop_zipfold() ->
|
||||
?FORALL(
|
||||
[Left, Right],
|
||||
[map(), map()],
|
||||
begin
|
||||
CommonKeys = maps_common_keys(Left, Right),
|
||||
|
||||
Actual =
|
||||
genlib_map:zipfold(
|
||||
fun(Key, LValue, RValue, Acc) -> Acc#{Key => {LValue, RValue}} end,
|
||||
#{},
|
||||
Left,
|
||||
Right
|
||||
),
|
||||
|
||||
Expected =
|
||||
maps_merge_with(
|
||||
fun(_Key, LValue, RValue) -> {LValue, RValue} end,
|
||||
Left,
|
||||
Right
|
||||
),
|
||||
|
||||
Actual =:= maps:with(CommonKeys, Expected)
|
||||
end
|
||||
).
|
||||
|
||||
-if(?OTP_RELEASE >= 24).
|
||||
|
||||
maps_merge_with(Combiner, Left, Right) ->
|
||||
maps:merge_with(Combiner, Left, Right).
|
||||
|
||||
-else.
|
||||
|
||||
maps_merge_with(Combiner, Left, Right) ->
|
||||
CommonMerged =
|
||||
lists:foldl(
|
||||
fun(Key, Acc) ->
|
||||
Acc#{Key => Combiner(Key, maps:get(Key, Left), maps:get(Key, Right))}
|
||||
end,
|
||||
#{},
|
||||
maps_common_keys(Left, Right)
|
||||
),
|
||||
|
||||
maps:merge(maps:merge(Left, Right), CommonMerged).
|
||||
|
||||
%% END -if(?OTP_RELEASE >= 24).
|
||||
-endif.
|
||||
|
||||
maps_common_keys(LeftMap, RightMap) ->
|
||||
sets:to_list(
|
||||
sets:intersection(
|
||||
sets:from_list(maps:keys(LeftMap)),
|
||||
sets:from_list(maps:keys(RightMap))
|
||||
)
|
||||
).
|
||||
|
||||
map() ->
|
||||
?LET(KVList, list({term(), term()}), maps:from_list(KVList)).
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user