aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src/ordsets.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/src/ordsets.erl')
-rw-r--r--lib/stdlib/src/ordsets.erl220
1 files changed, 220 insertions, 0 deletions
diff --git a/lib/stdlib/src/ordsets.erl b/lib/stdlib/src/ordsets.erl
new file mode 100644
index 0000000000..05041c15f1
--- /dev/null
+++ b/lib/stdlib/src/ordsets.erl
@@ -0,0 +1,220 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ordsets).
+
+-export([new/0,is_set/1,size/1,to_list/1,from_list/1]).
+-export([is_element/2,add_element/2,del_element/2]).
+-export([union/2,union/1,intersection/2,intersection/1]).
+-export([is_disjoint/2]).
+-export([subtract/2,is_subset/2]).
+-export([fold/3,filter/2]).
+
+-type ordset(T) :: [T].
+
+%% new() -> Set.
+%% Return a new empty ordered set.
+
+-spec new() -> ordset(term()).
+
+new() -> [].
+
+%% is_set(Term) -> boolean().
+%% Return 'true' if Set is an ordered set of elements, else 'false'.
+
+-spec is_set(term()) -> boolean().
+
+is_set([E|Es]) -> is_set(Es, E);
+is_set([]) -> true;
+is_set(_) -> false.
+
+is_set([E2|Es], E1) when E1 < E2 ->
+ is_set(Es, E2);
+is_set([_|_], _) -> false;
+is_set([], _) -> true.
+
+%% size(OrdSet) -> int().
+%% Return the number of elements in OrdSet.
+
+-spec size(ordset(_)) -> non_neg_integer().
+
+size(S) -> length(S).
+
+%% to_list(OrdSet) -> [Elem].
+%% Return the elements in OrdSet as a list.
+
+-spec to_list(ordset(T)) -> [T].
+
+to_list(S) -> S.
+
+%% from_list([Elem]) -> Set.
+%% Build an ordered set from the elements in List.
+
+-spec from_list([T]) -> ordset(T).
+
+from_list(L) ->
+ lists:usort(L).
+
+%% is_element(Element, OrdSet) -> boolean().
+%% Return 'true' if Element is an element of OrdSet, else 'false'.
+
+-spec is_element(term(), ordset(_)) -> boolean().
+
+is_element(E, [H|Es]) when E > H -> is_element(E, Es);
+is_element(E, [H|_]) when E < H -> false;
+is_element(_E, [_H|_]) -> true; %E == H
+is_element(_, []) -> false.
+
+%% add_element(Element, OrdSet) -> OrdSet.
+%% Return OrdSet with Element inserted in it.
+
+-spec add_element(term(), ordset(_)) -> ordset(_).
+
+add_element(E, [H|Es]) when E > H -> [H|add_element(E, Es)];
+add_element(E, [H|_]=Set) when E < H -> [E|Set];
+add_element(_E, [_H|_]=Set) -> Set; %E == H
+add_element(E, []) -> [E].
+
+%% del_element(Element, OrdSet) -> OrdSet.
+%% Return OrdSet but with Element removed.
+
+-spec del_element(term(), ordset(_)) -> ordset(_).
+
+del_element(E, [H|Es]) when E > H -> [H|del_element(E, Es)];
+del_element(E, [H|_]=Set) when E < H -> Set;
+del_element(_E, [_H|Es]) -> Es; %E == H
+del_element(_, []) -> [].
+
+%% union(OrdSet1, OrdSet2) -> OrdSet
+%% Return the union of OrdSet1 and OrdSet2.
+
+-spec union(ordset(_), ordset(_)) -> ordset(_).
+
+union([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
+ [E1|union(Es1, Set2)];
+union([E1|_]=Set1, [E2|Es2]) when E1 > E2 ->
+ [E2|union(Es2, Set1)]; % switch arguments!
+union([E1|Es1], [_E2|Es2]) -> %E1 == E2
+ [E1|union(Es1, Es2)];
+union([], Es2) -> Es2;
+union(Es1, []) -> Es1.
+
+%% union([OrdSet]) -> OrdSet
+%% Return the union of the list of ordered sets.
+
+-spec union([ordset(_)]) -> ordset(_).
+
+union([S1,S2|Ss]) ->
+ union1(union(S1, S2), Ss);
+union([S]) -> S;
+union([]) -> [].
+
+union1(S1, [S2|Ss]) -> union1(union(S1, S2), Ss);
+union1(S1, []) -> S1.
+
+%% intersection(OrdSet1, OrdSet2) -> OrdSet.
+%% Return the intersection of OrdSet1 and OrdSet2.
+
+-spec intersection(ordset(_), ordset(_)) -> ordset(_).
+
+intersection([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
+ intersection(Es1, Set2);
+intersection([E1|_]=Set1, [E2|Es2]) when E1 > E2 ->
+ intersection(Es2, Set1); % switch arguments!
+intersection([E1|Es1], [_E2|Es2]) -> %E1 == E2
+ [E1|intersection(Es1, Es2)];
+intersection([], _) ->
+ [];
+intersection(_, []) ->
+ [].
+
+%% intersection([OrdSet]) -> OrdSet.
+%% Return the intersection of the list of ordered sets.
+
+-spec intersection([ordset(_)]) -> ordset(_).
+
+intersection([S1,S2|Ss]) ->
+ intersection1(intersection(S1, S2), Ss);
+intersection([S]) -> S.
+
+intersection1(S1, [S2|Ss]) ->
+ intersection1(intersection(S1, S2), Ss);
+intersection1(S1, []) -> S1.
+
+%% is_disjoint(OrdSet1, OrdSet2) -> boolean().
+%% Check whether OrdSet1 and OrdSet2 are disjoint.
+
+-spec is_disjoint(ordset(_), ordset(_)) -> boolean().
+
+is_disjoint([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
+ is_disjoint(Es1, Set2);
+is_disjoint([E1|_]=Set1, [E2|Es2]) when E1 > E2 ->
+ is_disjoint(Es2, Set1); % switch arguments!
+is_disjoint([_E1|_Es1], [_E2|_Es2]) -> %E1 == E2
+ false;
+is_disjoint([], _) ->
+ true;
+is_disjoint(_, []) ->
+ true.
+
+%% subtract(OrdSet1, OrdSet2) -> OrdSet.
+%% Return all and only the elements of OrdSet1 which are not also in
+%% OrdSet2.
+
+-spec subtract(ordset(_), ordset(_)) -> ordset(_).
+
+subtract([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
+ [E1|subtract(Es1, Set2)];
+subtract([E1|_]=Set1, [E2|Es2]) when E1 > E2 ->
+ subtract(Set1, Es2);
+subtract([_E1|Es1], [_E2|Es2]) -> %E1 == E2
+ subtract(Es1, Es2);
+subtract([], _) -> [];
+subtract(Es1, []) -> Es1.
+
+%% is_subset(OrdSet1, OrdSet2) -> boolean().
+%% Return 'true' when every element of OrdSet1 is also a member of
+%% OrdSet2, else 'false'.
+
+-spec is_subset(ordset(_), ordset(_)) -> boolean().
+
+is_subset([E1|_], [E2|_]) when E1 < E2 -> %E1 not in Set2
+ false;
+is_subset([E1|_]=Set1, [E2|Es2]) when E1 > E2 ->
+ is_subset(Set1, Es2);
+is_subset([_E1|Es1], [_E2|Es2]) -> %E1 == E2
+ is_subset(Es1, Es2);
+is_subset([], _) -> true;
+is_subset(_, []) -> false.
+
+%% fold(Fun, Accumulator, OrdSet) -> Accumulator.
+%% Fold function Fun over all elements in OrdSet and return Accumulator.
+
+-spec fold(fun((_, _) -> _), _, ordset(_)) -> _.
+
+fold(F, Acc, Set) ->
+ lists:foldl(F, Acc, Set).
+
+%% filter(Fun, OrdSet) -> OrdSet.
+%% Filter OrdSet with Fun.
+
+-spec filter(fun((_) -> boolean()), ordset(_)) -> ordset(_).
+
+filter(F, Set) ->
+ lists:filter(F, Set).