%% Erlang maps utillity functions %% -module(maputils). %% API -export([make_hierarchi/2, make_hierarchi/3, deep_get/2]). %% API ------------------------------------------------------------------------ -type key() :: term(). -spec make_hierarchi([key()], map()) -> map(). make_hierarchi(Order, Maps) -> make_hierarchi(Order, Maps, dont_keep). -spec make_hierarchi([key()], map(), keep|dont_keep) -> map(). make_hierarchi([], Maps, _) -> Maps; make_hierarchi([Key|Order], Maps, Keep) -> Map = split_on_key(Key, Maps, Keep), F = fun(InnerKey, InnerMaps, Acc) -> Acc#{InnerKey=>make_hierarchi(Order, InnerMaps, Keep)} end, maps:fold(F, #{}, Map). -spec deep_get([key()], map()) -> term(). deep_get([Key|Keys], Map) -> case maps:find(Key, Map) of {ok, InnerMap} when is_map(InnerMap) -> deep_get(Keys, InnerMap); {ok, Val} -> Val; error -> {error, {key_not_found, Key}} end; deep_get([], Value) -> Value. %% Internal ------------------------------------------------------------------- split_on_key(Key, Maps, Keep) -> F = fun(#{Key:=Val} = Map, Acc) -> case maps:find(Val, Acc) of {ok, InnerMaps} when Keep == keep -> Acc#{Val:=[Map|InnerMaps]}; {ok, InnerMaps} when Keep == dont_keep -> Acc#{Val:=[maps:remove(Key, Map)|InnerMaps]}; error when Keep == keep -> Acc#{Val=>[Map]}; error when Keep == dont_keep -> Acc#{Val=>[maps:remove(Key, Map)]} end; (_, _) -> exit({key_not_found, Key}) end, lists:foldl(F, #{}, Maps).