[erlang-questions] Merging maps with a fun like dict:merge/3
Michael Truog
mjtruog@REDACTED
Wed Aug 26 22:21:03 CEST 2015
A straight-forward way to provide a maps merge function based on the dict documentation is:
maps_update(K, F, V0, Map) ->
try maps:get(K, Map) of
V1 ->
maps:put(K, F(V1), Map)
catch
error:{badkey, K} ->
maps:put(K, V0, Map)
end.
maps_merge(Fun, Map1, Map2) ->
maps:fold(fun (K, V1, Map) ->
maps_update(K, fun (V2) -> Fun(K, V1, V2) end, V1, Map)
end, Map2, Map1).
Not sure about the speed compared to the code below, but both results should be the same if everything is working properly.
On 08/26/2015 11:44 AM, Ivan Uemlianin wrote:
> Dear Alexander, Hynek
>
> That is a *lot* faster! :D
>
> Thanks very much both.
>
> Ivan
>
>
> On 08/26/15 10:38, Ivan Uemlianin wrote:
>> Oh yes of course that's better. Thanks
>>
>> Ivan
>>
>>
>> On 26/08/2015 10:32, Hynek Vychodil wrote:
>>> I would consider:
>>>
>>> merge_ap(F, [Head | Tail]) ->
>>> lists:foldl(fun(Y, X) ->
>>> maps:merge(X, maps:map(fun(Key, Value) ->
>>> case maps:find(Key, X) of
>>> {ok, V} -> F(Key, V, Value);
>>> error -> Value
>>> end
>>> end,
>>> Y))
>>> end,
>>> Head,
>>> Tail).
>>>
>>> On Wed, Aug 26, 2015 at 10:45 AM, Ivan Uemlianin <ivan@REDACTED> wrote:
>>>
>>> Dear Alexander
>>>
>>> Thanks! That looks excellent!
>>>
>>> I notice that your function F is different from the dict:merge/3 function: instead of taking a key and the two values, is takes two values, defaulting the first to 0.
>>>
>>> I've put my case clause into your framework:
>>>
>>> merge_ap(F, [Head | Tail]) ->
>>> lists:foldl(fun(Y, X) ->
>>> maps:merge(X, maps:map(fun(Key, Value) ->
>>> case maps:is_key(Key, X) of
>>> false ->
>>> Value;
>>> true ->
>>> F(Key, Value, maps:get(Key, X))
>>> end
>>> end,
>>> Y))
>>> end,
>>> Head,
>>> Tail).
>>>
>>> This has desired behaviour, and will probably still perform well. Using lists:foldl is a brilliant idea.
>>>
>>> Best wishes
>>>
>>> Ivan
>>>
>>>
>>>
>>> On 26/08/2015 09:16, Alexander Petrovsky wrote:
>>>> Hi!
>>>>
>>>> I've make some little benchmarks, and noticed that the most effective way is:
>>>>
>>>> merge(F, [Head | Tail]) ->
>>>> lists:foldl(fun(Y, X) -> maps:merge(X, maps:map(fun(Key, Value) -> F(maps:get(Key, X, 0), Value) end, Y)) end, Head, Tail).
>>>>
>>>>
>>>> 2015-08-23 20:05 GMT+03:00 Ivan Uemlianin <ivan@REDACTED>:
>>>>
>>>> Dear All
>>>>
>>>> The maps module does not have a merge/3 like dict:merge/3, which calls a function fun(Key, Val1, Val2) when both dicts have the same key. From the documentation, "If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value."
>>>>
>>>> The dict documentation says that dict:merge/3 is faster than an equivalent implemented in erlang.
>>>>
>>>> http://www.erlang.org/doc/man/dict.html#merge-3
>>>>
>>>> Why does the maps module not have a similar merge/3? Is it because writing our own erlang implementation is at fast as it gets?
>>>>
>>>> Below is an implementation which seems to work. Can it be made faster?
>>>>
>>>>
>>>> merge_maps(Fun, M1, M2) ->
>>>> maps:fold(fun(K, V1, Acc) ->
>>>> case maps:is_key(K, Acc) of
>>>> false ->
>>>> maps:put(K, V1, Acc);
>>>> true ->
>>>> V2 = maps:get(K, Acc),
>>>> maps:put(K, Fun(K, V1, V2), Acc)
>>>> end
>>>> end,
>>>> M1,
>>>> M2).
>>>>
>>>> merge_maps_test() ->
>>>> merge_maps(fun(_K, V1, V2) -> V1 + V2 end,
>>>> #{a => 1, b => 2, c => 3},
>>>> #{b => 2, c => 3, d => 4}) =:=
>>>> #{a => 1, b => 4, c => 6, d => 4}.
>>>>
>>>>
>>>> With thanks and best wishes
>>>>
>>>> Ivan
>>>>
>>>> --
>>>> ============================================================
>>>> Ivan A. Uemlianin PhD
>>>> Llaisdy
>>>> Speech Technology Research and Development
>>>>
>>>> ivan@REDACTED
>>>> @llaisdy
>>>> llaisdy.wordpress.com <http://llaisdy.wordpress.com>
>>>> github.com/llaisdy <http://github.com/llaisdy>
>>>> www.linkedin.com/in/ivanuemlianin
>>>>
>>>> festina lente
>>>> ============================================================
>>>>
>>>> _______________________________________________
>>>> erlang-questions mailing list
>>>> erlang-questions@REDACTED <mailto:erlang-questions@REDACTED>
>>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Петровский Александр / Alexander Petrovsky,
>>>>
>>>> Skype: askjuise
>>>> Phone: +7 914 8 820 815
>>>>
>>>
>>> --
>>> ============================================================
>>> Ivan A. Uemlianin PhD
>>> Llaisdy
>>> Speech Technology Research and Development
>>>
>>> ivan@REDACTED <mailto:ivan@REDACTED>
>>> @llaisdy
>>> llaisdy.wordpress.com <http://llaisdy.wordpress.com>
>>> github.com/llaisdy <http://github.com/llaisdy>
>>> www.linkedin.com/in/ivanuemlianin <http://www.linkedin.com/in/ivanuemlianin>
>>>
>>> festina lente
>>> ============================================================
>>>
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> erlang-questions@REDACTED <mailto:erlang-questions@REDACTED>
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>>>
>>
>> --
>> ============================================================
>> Ivan A. Uemlianin PhD
>> Llaisdy
>> Speech Technology Research and Development
>>
>> ivan@REDACTED
>> @llaisdy
>> llaisdy.wordpress.com
>> github.com/llaisdy
>> www.linkedin.com/in/ivanuemlianin
>>
>> festina lente
>> ============================================================
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>
> --
> ============================================================
> Ivan A. Uemlianin PhD
> Llaisdy
> Speech Technology Research and Development
>
> ivan@REDACTED
> @llaisdy
> llaisdy.wordpress.com
> github.com/llaisdy
> www.linkedin.com/in/ivanuemlianin
>
> festina lente
> ============================================================
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150826/bc2d64dc/attachment.htm>
More information about the erlang-questions
mailing list