Write a function map_search_pred(Map, Pred) that returns the first element {Key,Value} in the map for which Pred(Key, Value) is true.
map_search_pred(Map, Pred) -> M = [{Key, Value} || {Key, Value} <- maps:to_list(Map), Pred(Key, Value) =:= true], case length(M) of 0 -> {}; _ -> lists:nth(1, M) end.
make(0, M, _) -> M; make(K, M, I) -> make(K-1,maps:put(I,I+1,M),I+2).
test(K) -> Map = make(K, #{}, 1), Map1 = Map#{0 => 0}, Map2 = Map#{123456789 => 123456789}, List1 = maps:to_list(Map1), List2 = maps:to_list(Map2), J1 = timer:tc(?MODULE, map_search_pred,[Map1,fun(X,Y) -> X =:= Y end]), J2 = timer:tc(?MODULE, map_search_pred,[Map2,fun(X,Y) -> X =:= Y end]), ...
> The results of this first test puzzled me at first. But hang on, I > know that a) > **performance measurement is difficult** b) **My intuition > about performance is always wrong**.
J3 = timer:tc(?MODULE, map_search_pred1, [Map2, fun(X, Y) when X =:= Y -> throw({X,Y}); (_,_) -> false end]),
map_search_pred1(A, B) -> (catch map_search_pred(A,B)).
{length,20000}, {maps_at_start,{6479,{0,0}}}, {maps_at_end,{2327,{123456789,123456789}}}, <- 1) should be the same maps_at_start {maps_thrown,{1814,{123456789,123456789}}}, <- 2) it is faster {maps_foldl,{2486,{123456789,123456789}}}, {lists_start,{2,{0,0}}}, {lists_end,{1221,{123456789,123456789}}}}
> The notion of ``order'' in a map is unclear. I know that maps are > printed in lexical order, but I don't know if they are stored > internally in the same order as which they are printed. > And they might perform differently if the maps have > a small or large number of elements.
> and lists in Erlang aren't even `lists`. They are really `stacks` - > but that's another story, and changing the name would not be a good > idea.
fold(Fun, In it, Map) when is_function(Fun,3), is_map(Map) -> lists:fold(fun({K,V},A) -> Fun(K,V,A) end,In it,maps:to_list(Map)).
find_first([H|T], Pred) -> case Pred(H) of true -> H; false -> find_first(T, Pred) end; find_first([], _) -> {}.
> p1:test(20000). {length,20000}, {maps_at_start,{6215,{0,0}}}, {maps_at_end,{2253,{123456789,123456789}}}, {maps_thrown,{1827,{123456789,123456789}}}, {maps_fold,{2698,{123456789,123456789}}}, {lists_start,{3,{0,0}}}, {lists_end,{1229,{123456789,123456789}}}}
-module(maps_timings). -compile(export_all). map_search_pred(Map, Pred) -> M = [{Key, Value} || {Key, Value} <- maps:to_list(Map), Pred(Key, Value) =:= true], case length(M) of 0 -> {}; _ -> lists:nth(1, M) end. map_search_pred1(A, B) -> (catch map_search_pred(A,B)). test(K) -> Map = make(K, #{}, 1), Map1 = Map#{0 => 0}, Map2 = Map#{123456789 => 123456789}, List1 = maps:to_list(Map1), List2 = maps:to_list(Map2), J1 = timer:tc(?MODULE, map_search_pred,[Map1,fun(X,Y) -> X =:= Y end]), J2 = timer:tc(?MODULE, map_search_pred,[Map2,fun(X,Y) -> X =:= Y end]), J3 = timer:tc(?MODULE, map_search_pred1, [Map2, fun(X, Y) when X =:= Y -> throw({X,Y}); (_,_) -> false end]), J4 = timer:tc(?MODULE, faster, [Map2, fun(X, Y, _) when X =:= Y -> throw({X,Y}); (_,_, A) -> A end]), J5 = timer:tc(?MODULE, find_first, [List1, fun({X, Y}) -> X =:= Y end]), J6 = timer:tc(?MODULE, find_first, [List2, fun({X, Y}) -> X =:= Y end]), { {length,K}, {maps_at_start,J1}, {maps_at_end,J2}, {maps_thrown,J3}, {maps_foldl,J4}, {lists_start,J5}, {lists_end,J6}}. make(0, M, _) -> M; make(K, M, I) -> make(K-1,maps:put(I,I+1,M),I+2). faster(Map, Fun) -> case catch (maps:fold(Fun, [], Map)) of [] -> {}; Other -> Other end. find_first([H|T], Pred) -> case Pred(H) of true -> H; false -> find_first(T, Pred) end; find_first([], _) -> {}.