Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:19
erlang
3931-Add-maps-groups_from_list.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3931-Add-maps-groups_from_list.patch of Package erlang
From 306f8bd8dbba91632d1bec536d7a0288fd1b8ee4 Mon Sep 17 00:00:00 2001 From: Gian Lorenzo Meocci <glmeocci@gmail.com> Date: Thu, 6 Jan 2022 15:23:32 +0100 Subject: [PATCH] Add maps:groups_from_list --- lib/stdlib/doc/src/maps.xml | 36 ++++++++++++++- lib/stdlib/src/erl_stdlib_errors.erl | 4 ++ lib/stdlib/src/maps.erl | 66 +++++++++++++++++++++++++++- lib/stdlib/test/maps_SUITE.erl | 23 +++++++++- 4 files changed, 125 insertions(+), 4 deletions(-) diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml index ea0f16eec9..a8793e86d1 100644 --- a/lib/stdlib/doc/src/maps.xml +++ b/lib/stdlib/doc/src/maps.xml @@ -606,7 +606,7 @@ error</code> maps:update_with("new counter",Fun,42,Map). #{"counter" => 1,"new counter" => 42}</code> </desc> - </func> + </func> <func> <name name="values" arity="1"/> @@ -657,5 +657,39 @@ error</code> #{1337 => "value two"}</code> </desc> </func> + + <func> + <name name="groups_from_list" arity="2"/> + <fsummary>Splits the list into groups using a function as discriminator.</fsummary> + <desc> + <p>The result is a map where each key is given by <anno>Fun</anno> + and each value is a list of elements. The order of elements within + each list is preserved from the list.</p> + <p><em>Examples:</em></p> + <pre> +> <input>maps:groups_from_list(fun(X) -> X rem 2 end, [1,2,3]).</input> +#{0 => [2], 1 => [1, 3]} +> <input>maps:groups_from_list(fun erlang:length/1, ["ant", "buffalo", "cat", "dingo"]).</input> +#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}</pre> + </desc> + </func> + + <func> + <name name="groups_from_list" arity="3"/> + <fsummary>Splits the list into groups using a function as discriminator.</fsummary> + <desc> + <p>The result is a map where each key is given by + <anno>Fun</anno> and each value is a list of elements given by + the <anno>ValueFun</anno>. The order of elements within each + list is preserved from the list.</p> + <p><em>Examples:</em></p> + <pre> +> <input>maps:groups_from_list(fun(X) -> X rem 2 end, fun(X) -> X*X end, [1,2,3]).</input> +#{0 => [4], 1 => [1, 9]} +> <input>maps:groups_from_list(fun erlang:length/1, fun lists:reverse/1, ["ant", "buffalo", "cat", "dingo"]).</input> +#{3 => ["tna","tac"],5 => ["ognid"],7 => ["olaffub"]}</pre> + </desc> + </func> + </funcs> </erlref> diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl index e6192eb22b..e3fb532750 100644 --- a/lib/stdlib/src/maps.erl +++ b/lib/stdlib/src/maps.erl @@ -26,7 +26,8 @@ -export([get/3, filter/2,fold/3, map/2, size/1, update_with/3, update_with/4, - without/2, with/2]). + without/2, with/2, + groups_from_list/2, groups_from_list/3]). %% BIFs -export([get/2, find/2, from_list/1, @@ -497,5 +498,68 @@ with_1([K|Ks], Map) -> end; with_1([], _Map) -> []. +%% groups_from_list/2 & groups_from_list/3 + +-spec groups_from_list(Fun, List) -> MapOut when + Fun :: fun((Elem :: T) -> Selected), + MapOut :: #{Selected => List}, + Selected :: term(), + List :: [T], + T :: term(). + +groups_from_list(Fun, List0) when is_function(Fun, 1) -> + try lists:reverse(List0) of + List -> + groups_from_list_1(Fun, List, #{}) + catch + error:_ -> + erlang:error(badarg, [Fun, List0]) + end; +groups_from_list(Fun, List) -> + erlang:error(badarg, [Fun, List]). + +groups_from_list_1(Fun, [H | Tail], Acc) -> + K = Fun(H), + NewAcc = case Acc of + #{K := Vs} -> Acc#{K := [H | Vs]}; + #{} -> Acc#{K => [H]} + end, + groups_from_list_1(Fun, Tail, NewAcc); +groups_from_list_1(_Fun, [], Acc) -> + Acc. + +-spec groups_from_list(Fun, ValueFun, List) -> MapOut when + Fun :: fun((Elem :: T) -> Key), + ValueFun :: fun((Elem :: T) -> ValOut), + MapOut :: #{Key := ListOut}, + Key :: term(), + ValOut :: term(), + List :: [T], + ListOut :: [ValOut], + T :: term(). + +groups_from_list(Fun, ValueFun, List0) when is_function(Fun, 1), + is_function(ValueFun, 1) -> + try lists:reverse(List0) of + List -> + groups_from_list_2(Fun, ValueFun, List, #{}) + catch + error:_ -> + erlang:error(badarg, [Fun, ValueFun, List0]) + end; +groups_from_list(Fun, ValueFun, List) -> + erlang:error(badarg, [Fun, ValueFun, List]). + +groups_from_list_2(Fun, ValueFun, [H | Tail], Acc) -> + K = Fun(H), + V = ValueFun(H), + NewAcc = case Acc of + #{K := Vs} -> Acc#{K := [V | Vs]}; + #{} -> Acc#{K => [V]} + end, + groups_from_list_2(Fun, ValueFun, Tail, NewAcc); +groups_from_list_2(_Fun, _ValueFun, [], Acc) -> + Acc. + error_type(M) when is_map(M) -> badarg; error_type(V) -> {badmap, V}. diff --git a/lib/stdlib/test/maps_SUITE.erl b/lib/stdlib/test/maps_SUITE.erl index 28895c4efe..2492130cf1 100644 --- a/lib/stdlib/test/maps_SUITE.erl +++ b/lib/stdlib/test/maps_SUITE.erl @@ -42,7 +42,8 @@ t_get_3/1, t_filter_2/1, t_fold_3/1,t_map_2/1,t_size_1/1, t_put_opt/1, t_merge_opt/1, - t_with_2/1,t_without_2/1]). + t_with_2/1,t_without_2/1, + t_groups_from_list/1]). %%-define(badmap(V,F,Args), {'EXIT', {{badmap,V}, [{maps,F,Args,_}|_]}}). %%-define(badarg(F,Args), {'EXIT', {badarg, [{maps,F,Args,_}|_]}}). @@ -68,7 +69,8 @@ all() -> t_get_3,t_filter_2, t_fold_3,t_map_2,t_size_1, t_put_opt,t_merge_opt, - t_with_2,t_without_2]. + t_with_2,t_without_2, + t_groups_from_list]. t_update_with_3(Config) when is_list(Config) -> V1 = value1, @@ -770,4 +772,14 @@ t_size_1(Config) when is_list(Config) -> ?badmap(<<>>,size,[<<>>]) = (catch maps:size(id(<<>>))), ok. +t_groups_from_list(_Config) -> + #{} = maps:groups_from_list(fun erlang:length/1, []), + #{3 := ["tna","tac"], 5 := ["ognid"], 7 := ["olaffub"]} = + maps:groups_from_list( + fun erlang:length/1, + fun lists:reverse/1, + ["ant", "buffalo", "cat", "dingo"] + ), + #{0 := [2], 1 := [1, 3]} = maps:groups_from_list(fun(X) -> X rem 2 end, [1, 2, 3]). + id(I) -> I. -- 2.34.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor