diff options
author | Maria-12648430 <maria-12648430@gmx.net> | 2020-11-25 10:05:36 +0100 |
---|---|---|
committer | Maria-12648430 <maria-12648430@gmx.net> | 2020-11-25 10:05:36 +0100 |
commit | c54720eaa52d3c12c2a49ab0aa4950589b2b0b80 (patch) | |
tree | 53192308db60fbbae14f9806536950dfaf0fe0f6 | |
parent | cb475e0126fc647ea5d97a58bb0d91139b7c6d02 (diff) | |
download | erlang-c54720eaa52d3c12c2a49ab0aa4950589b2b0b80.tar.gz |
Add delete_with/delete_with_r to the queue module
-rw-r--r-- | lib/stdlib/doc/src/queue.xml | 28 | ||||
-rw-r--r-- | lib/stdlib/src/queue.erl | 75 | ||||
-rw-r--r-- | lib/stdlib/test/queue_SUITE.erl | 12 |
3 files changed, 112 insertions, 3 deletions
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml index 9d353fb856..08320f4ec4 100644 --- a/lib/stdlib/doc/src/queue.xml +++ b/lib/stdlib/doc/src/queue.xml @@ -57,6 +57,8 @@ <seemfa marker="#any/2"><c>any/2</c></seemfa>, <seemfa marker="#delete/2"><c>delete/2</c></seemfa>, <seemfa marker="#delete_r/2"><c>delete_r/2</c></seemfa>, + <seemfa marker="#delete_with/2"><c>delete_with/2</c></seemfa>, + <seemfa marker="#delete_with_r/2"><c>delete_with_r/2</c></seemfa>, <seemfa marker="#filter/2"><c>filter/2</c></seemfa>, <seemfa marker="#filtermap/2"><c>filtermap/2</c></seemfa>, <seemfa marker="#fold/3"><c>fold/3</c></seemfa>, @@ -147,7 +149,7 @@ <desc> <p>Returns a copy of <c><anno>Q1</anno></c> where the first item matching <c><anno>Item</anno></c> is deleted, if there is such an - element.</p> + item.</p> </desc> </func> @@ -157,7 +159,29 @@ <desc> <p>Returns a copy of <c><anno>Q1</anno></c> where the last item matching <c><anno>Item</anno></c> is deleted, if there is such an - element.</p> + item.</p> + </desc> + </func> + + <func> + <name name="delete_with" arity="2" since=""/> + <fsummary>Delete an item matching a predicate from the front of a + queue.</fsummary> + <desc> + <p>Returns a copy of <c><anno>Q1</anno></c> where the first item + for which <c><anno>Pred</anno></c> returns <c>true</c> is deleted, + if there is such an item.</p> + </desc> + </func> + + <func> + <name name="delete_with_r" arity="2" since=""/> + <fsummary>Delete an item matching a predicate from the rear of a + queue.</fsummary> + <desc> + <p>Returns a copy of <c><anno>Q1</anno></c> where the last item + for which <c><anno>Pred</anno></c> returns <c>true</c> is deleted, + if there is such an item.</p> </desc> </func> diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl index 2447f68946..2bbffcc753 100644 --- a/lib/stdlib/src/queue.erl +++ b/lib/stdlib/src/queue.erl @@ -28,7 +28,7 @@ %% Higher level API -export([reverse/1,join/2,split/2,filter/2,filtermap/2,fold/3,any/2,all/2, - delete/2,delete_r/2]). + delete/2,delete_r/2,delete_with/2,delete_with_r/2]). %% Okasaki API from klacke -export([cons/2,head/1,tail/1, @@ -541,6 +541,79 @@ delete_rear(Item, [X|Rest]) -> delete_rear(_, []) -> false. +%% Delete the first occurence of an item in the queue +%% matching a predicate, according to queue order. +%% +%% O(len(Q1)) worst case +-spec delete_with(Pred, Q1) -> Q2 when + Pred :: fun((Item) -> boolean()), + Q1 :: queue(Item), + Q2 :: queue(Item), + Item :: term(). +delete_with(Pred, {R0, F0} = Q) when is_function(Pred, 1), is_list(R0), is_list(F0) -> + case delete_with_front(Pred, F0) of + false -> + case delete_with_rear(Pred, R0) of + false -> + Q; + [] -> + f2r(F0); + R1 -> + {R1, F0} + end; + [] -> + r2f(R0); + F1 -> + {R0, F1} + end; +delete_with(Pred, Q) -> + erlang:error(badarg, [Pred, Q]). + +%% Delete the last occurence of an item in the queue +%% matching a predicate, according to queue order. +%% +%% O(len(Q1)) worst case +-spec delete_with_r(Pred, Q1) -> Q2 when + Pred :: fun((Item) -> boolean()), + Q1 :: queue(Item), + Q2 :: queue(Item), + Item :: term(). +delete_with_r(Pred, {R0, F0}) when is_function(Pred, 1), is_list(R0), is_list(F0) -> + {F1, R1} = delete_with(Pred, {F0, R0}), + {R1, F1}; +delete_with_r(Pred, Q) -> + erlang:error(badarg, [Pred, Q]). + +delete_with_front(Pred, [X|Rest]) -> + case Pred(X) of + true -> + Rest; + false -> + case delete_with_front(Pred, Rest) of + false -> + false; + F -> + [X|F] + end + end; +delete_with_front(_, []) -> + false. + +delete_with_rear(Pred, [X|Rest]) -> + case delete_with_rear(Pred, Rest) of + false -> + case Pred(X) of + true -> + Rest; + false -> + false + end; + R -> + [X|R] + end; +delete_with_rear(_, []) -> + false. + %%-------------------------------------------------------------------------- %% Okasaki API inspired by an Erlang user contribution "deque.erl" %% by Claes Wikstrom <klacke@kaja.klacke.net> 1999. diff --git a/lib/stdlib/test/queue_SUITE.erl b/lib/stdlib/test/queue_SUITE.erl index 71af5fcf2d..9623e08f04 100644 --- a/lib/stdlib/test/queue_SUITE.erl +++ b/lib/stdlib/test/queue_SUITE.erl @@ -412,6 +412,18 @@ do_op_test(F) -> [1,3] = queue:to_list(queue:delete_r(x, queue:from_list([1,x,3]))), [1,2] = queue:to_list(queue:delete_r(x, queue:from_list([1,2,x]))), [x,1,2] = queue:to_list(queue:delete_r(x, queue:from_list([x,1,2,x]))), + [] = queue:to_list(queue:delete_with(fun(_) -> false end, queue:new())), + [1,2,3] = queue:to_list(queue:delete_with(fun(X) -> X<0 end, queue:from_list([1,2,3]))), + [2,3] = queue:to_list(queue:delete_with(fun(X) -> X>0 end, queue:from_list([1,2,3]))), + [1,3] = queue:to_list(queue:delete_with(fun(X) -> X>1 end, queue:from_list([1,2,3]))), + [1,2] = queue:to_list(queue:delete_with(fun(X) -> X>2 end, queue:from_list([1,2,3]))), + [1,2,3] = queue:to_list(queue:delete_with(fun(X) -> X>1 end, queue:from_list([1,2,2,3]))), + [] = queue:to_list(queue:delete_with_r(fun(_) -> false end, queue:new())), + [1,2,3] = queue:to_list(queue:delete_with_r(fun(X) -> X>9 end, queue:from_list([1,2,3]))), + [1,2] = queue:to_list(queue:delete_with_r(fun(X) -> X<9 end, queue:from_list([1,2,3]))), + [1,3] = queue:to_list(queue:delete_with_r(fun(X) -> X<3 end, queue:from_list([1,2,3]))), + [2,3] = queue:to_list(queue:delete_with_r(fun(X) -> X<2 end, queue:from_list([1,2,3]))), + [1,2,3] = queue:to_list(queue:delete_with_r(fun(X) -> X<3 end, queue:from_list([1,2,2,3]))), %% ok. |