Pure (immutable) sets based on order/comparison of elements. A set is a collection of elements without duplicates. The set data structure type is stable and can be used for orthogonal persistence.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter([3, 1, 2, 3].values(), Nat.compare);
assert Set.size(set) == 3;
assert not Set.contains(set, Nat.compare, 4);
let diff = Set.difference(set, set, Nat.compare);
assert Set.isEmpty(diff);
}
These sets are implemented as red-black trees, a balanced binary search tree of ordered elements.
The tree data structure internally colors each of its nodes either red or black, and uses this information to balance the tree during modifying operations.
Performance:
O(log(n)) worst case cost per insertion, removal, and retrieval operation.O(n) for storing the entire tree.
n denotes the number of elements (i.e. nodes) stored in the tree.Credits:
The core of this implementation is derived from:
Ordered collection of unique elements of the generic type T.
If type T is stable then Set<T> is also stable.
To ensure that property the Set<T> does not have any methods,
instead they are gathered in the functor-like class Operations (see example there).
@deprecated M0235
public func fromIter<T>(iter : Iter.Iter<T>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>Create a set with the elements obtained from an iterator. Potential duplicate elements in the iterator are ignored, i.e. multiple occurrences of an equal element only occur once in the set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set = Set.fromIter([3, 1, 2, 1].values(), Nat.compare);
assert Iter.toArray(Set.values(set)) == [1, 2, 3];
}
Runtime: O(n * log(n)).
Space: O(n).
where n denotes the number of elements returned by the iterator and
assuming that the compare function implements an O(1) comparison.
Note: Creates O(n * log(n)) temporary objects that will be collected as garbage.
public func toSet<T>(self : Iter.Iter<T>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>Convert an iterator into a set. Potential duplicate elements in the iterator are ignored, i.e. multiple occurrences of an equal element only occur once in the set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
transient let iter = [3, 1, 2, 1].values();
let set = iter.toSet(Nat.compare);
assert Iter.toArray(Set.values(set)) == [1, 2, 3];
}
Runtime: O(n * log(n)).
Space: O(n).
where n denotes the number of elements returned by the iterator and
assuming that the compare function implements an O(1) comparison.
Note: Creates O(n * log(n)) temporary objects that will be collected as garbage.
public func add<T>(
self : Set<T>,
compare : (implicit : (T, T) -> Order.Order),
elem : T
) : Set<T>Given a set ordered by compare, insert the new element,
returning the new set.
Return the set unchanged if the element already exists in the set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set0 = Set.empty<Nat>();
let set1 = Set.add(set0, Nat.compare, 2);
let set2 = Set.add(set1, Nat.compare, 1);
let set3 = Set.add(set2, Nat.compare, 2);
assert Iter.toArray(Set.values(set0)) == [];
assert Iter.toArray(Set.values(set1)) == [2];
assert Iter.toArray(Set.values(set2)) == [1, 2];
assert Iter.toArray(Set.values(set3)) == [1, 2];
}
Runtime: O(log(n)).
Space: O(log(n)).
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
Note: The returned set shares with the set most of the tree nodes.
Garbage collecting one of the sets (e.g. after an assignment m := Set.add(m, c, e))
causes collecting O(log(n)) nodes.
public func insert<T>(
self : Set<T>,
compare : (implicit : (T, T) -> Order.Order),
elem : T
) : (Set<T>, Bool)Given set ordered by compare, insert the new element,
returning the set extended with element and a Boolean indicating
if the element was already present in set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set0 = Set.empty();
do {
let (set1, new1) = Set.insert(set0, Nat.compare, 2);
assert new1;
let (set2, new2) = Set.insert(set1, Nat.compare, 1);
assert new2;
let (set3, new3) = Set.insert(set2, Nat.compare, 2);
assert not new3;
assert Iter.toArray(Set.values(set3)) == [1, 2]
}
}
Runtime: O(log(n)).
Space: O(log(n)).
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
Note: The returned set shares with the set most of the tree nodes.
Garbage collecting one of the sets (e.g. after an assignment m := Set.add(m, c, e))
causes collecting O(log(n)) nodes.
public func remove<T>(
self : Set<T>,
compare : (implicit : (T, T) -> Order.Order),
element : T
) : Set<T>Given set ordered by compare return the set with element removed.
Return the set unchanged if the element was absent.
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set = Set.fromIter([1, 2, 3].values(), Nat.compare);
let set1 = Set.remove(set, Nat.compare, 2);
let set2 = Set.remove(set1, Nat.compare, 4);
assert Iter.toArray(Set.values(set2)) == [1, 3];
}
Runtime: O(log(n)).
Space: O(log(n)) including garbage, see below.
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
Note: Creates O(log(n)) objects that will be collected as garbage.
Note: The returned set shares with set most of the tree nodes.
Garbage collecting one of the sets (e.g. after an assignment m := Set.delete(m, c, e))
causes collecting O(log(n)) nodes.
public func delete<T>(
self : Set<T>,
compare : (implicit : (T, T) -> Order.Order),
element : T
) : (Set<T>, Bool)Given set ordered by compare, delete element from the set, returning
either the set without the element and a Boolean indicating whether
whether element was contained in set.
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set = Set.fromIter([1, 2, 3].values(), Nat.compare);
do {
let (set1, contained1) = Set.delete(set, Nat.compare, 2);
assert contained1;
assert Iter.toArray(Set.values(set1)) == [1, 3];
let (set2, contained2) = Set.delete(set1, Nat.compare, 4);
assert not contained2;
assert Iter.toArray(Set.values(set2)) == [1, 3];
}
}
Runtime: O(log(n)).
Space: O(log(n)) including garbage, see below.
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
Note: Creates O(log(n)) objects that will be collected as garbage.
Note: The returned set shares with set most of the tree nodes.
Garbage collecting one of the sets (e.g. after an assignment m := Set.delete(m, c, e))
causes collecting O(log(n)) nodes.
public func contains<T>(
self : Set<T>,
compare : (implicit : (T, T) -> Order.Order),
element : T
) : BoolTests whether the set contains the provided element.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Bool "mo:core/Bool";
persistent actor {
let set = Set.fromIter([3, 1, 2].values(), Nat.compare);
assert Set.contains(set, Nat.compare, 1);
assert not Set.contains(set, Nat.compare, 4);
}
Runtime: O(log(n)).
Space: O(1) retained memory plus garbage, see the note below.
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
public func max<T>(self : Set<T>) : ?TGet the maximal element of the set set if it is not empty, otherwise returns null
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set1 = Set.fromIter<Nat>([0, 2, 1].values(), Nat.compare);
let set2 = Set.empty<Nat>();
assert Set.max(set1) == ?2;
assert Set.max(set2) == null;
}
Runtime: O(log(n)).
Space: O(1).
where n denotes the number of elements in the set
public func min<T>(self : Set<T>) : ?TRetrieves the minimum element from the set.
If the set is empty, returns null.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set1 = Set.fromIter<Nat>([2, 0, 1].values(), Nat.compare);
let set2 = Set.empty<Nat>();
assert Set.min(set1) == ?0;
assert Set.min(set2) == null;
}
Runtime: O(log(n)).
Space: O(1).
where n denotes the number of elements stored in the set.
public func union<T>(
self : Set<T>,
other : Set<T>,
compare : (implicit : (T, T) -> Order.Order)
) : Set<T>Returns a new set that is the union of set1 and set2,
i.e. a new set that all the elements that exist in at least on of the two sets.
Potential duplicates are ignored, i.e. if the same element occurs in both set1
and set2, it only occurs once in the returned set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set1 = Set.fromIter([1, 2, 3].values(), Nat.compare);
let set2 = Set.fromIter([3, 4, 5].values(), Nat.compare);
let union = Set.union(set1, set2, Nat.compare);
assert Iter.toArray(Set.values(union)) == [1, 2, 3, 4, 5];
}
Runtime: O(m * log(n)).
Space: O(m), retained memory plus garbage, see the note below.
where m and n denote the number of elements in the sets, and m <= n.
and assuming that the compare function implements an O(1) comparison.
Note: Creates O(m * log(n)) temporary objects that will be collected as garbage.
public func intersection<T>(
self : Set<T>,
other : Set<T>,
compare : (implicit : (T, T) -> Order.Order)
) : Set<T>Returns a new set that is the intersection of set1 and set2,
i.e. a new set that contains all the elements that exist in both sets.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set1 = Set.fromIter([0, 1, 2].values(), Nat.compare);
let set2 = Set.fromIter([1, 2, 3].values(), Nat.compare);
let intersection = Set.intersection(set1, set2, Nat.compare);
assert Iter.toArray(Set.values(intersection)) == [1, 2];
}
Runtime: O(m * log(n)).
Space: O(1) retained memory plus garbage, see the note below.
where m and n denote the number of elements stored in the sets set1 and set2, respectively,
and assuming that the compare function implements an O(1) comparison.
Note: Creates O(m) temporary objects that will be collected as garbage.
public func difference<T>(
self : Set<T>,
other : Set<T>,
compare : (implicit : (T, T) -> Order.Order)
) : Set<T>Returns a new set that is the difference between set1 and other (set1 minus set2),
i.e. a new set that contains all the elements of set1 that do not exist in set2.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set1 = Set.fromIter([1, 2, 3].values(), Nat.compare);
let set2 = Set.fromIter([3, 4, 5].values(), Nat.compare);
let difference = Set.difference(set1, set2, Nat.compare);
assert Iter.toArray(Set.values(difference)) == [1, 2];
}
Runtime: O(m * log(n)).
Space: O(1) retained memory plus garbage, see the note below.
where m and n denote the number of elements stored in the sets set1 and set2, respectively,
and assuming that the compare function implements an O(1) comparison.
Note: Creates O(m * log(n)) temporary objects that will be collected as garbage.
public func map<T1, T2>(
self : Set<T1>,
compare : (implicit : (T2, T2) -> Order.Order),
project : T1 -> T2
) : Set<T2>Project all elements of the set in a new set. Apply a mapping function to each element in the set and collect the mapped elements in a new mutable set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Text "mo:core/Text";
import Iter "mo:core/Iter";
persistent actor {
let numbers = Set.fromIter([3, 1, 2].values(), Nat.compare);
let textNumbers =
Set.map<Nat, Text>(numbers, Text.compare, Nat.toText);
assert Iter.toArray(Set.values(textNumbers)) == ["1", "2", "3"];
}
Runtime: O(n * log(n)).
Space: O(n) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
Note: Creates O(n * log(n)) temporary objects that will be collected as garbage.
public func forEach<T>(self : Set<T>, operation : T -> ())Apply an operation on each element contained in the set. The operation is applied in ascending order of the elements.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let numbers = Set.fromIter([0, 3, 1, 2].values(), Nat.compare);
var text = "";
Set.forEach<Nat>(numbers, func (element) {
text #= " " # Nat.toText(element)
});
assert text == " 0 1 2 3";
}
Runtime: O(n).
Space: O(1) retained memory.
where n denotes the number of elements stored in the set.
public func filter<T>(
self : Set<T>,
compare : (implicit : (T, T) -> Order.Order),
criterion : T -> Bool
) : Set<T>Filter elements in a new set. Create a copy of the mutable set that only contains the elements that fulfil the criterion function.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let numbers = Set.fromIter([0, 3, 1, 2].values(), Nat.compare);
let evenNumbers = Set.filter<Nat>(numbers, Nat.compare, func (number) {
number % 2 == 0
});
assert Iter.toArray(Set.values(evenNumbers)) == [0, 2];
}
Runtime: O(n).
Space: O(n).
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
public func filterMap<T1, T2>(
self : Set<T1>,
compare : (implicit : (T2, T2) -> Order.Order),
project : T1 -> ?T2
) : Set<T2>Filter all elements in the set by also applying a projection to the elements.
Apply a mapping function project to all elements in the set and collect all
elements, for which the function returns a non-null new element. Collect all
non-discarded new elements in a new mutable set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Text "mo:core/Text";
import Iter "mo:core/Iter";
persistent actor {
let numbers = Set.fromIter([3, 0, 2, 1].values(), Nat.compare);
let evenTextNumbers = Set.filterMap<Nat, Text>(numbers, Text.compare, func (number) {
if (number % 2 == 0) {
?Nat.toText(number)
} else {
null // discard odd numbers
}
});
assert Iter.toArray(Set.values(evenTextNumbers)) == ["0", "2"];
}
Runtime: O(n * log(n)).
Space: O(n) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set.
Note: Creates O(log(n)) temporary objects that will be collected as garbage.
Runtime: O(n * log(n)).
Space: O(n) retained memory plus garbage, see the note below.
where n denotes the number of elements stored in the set and
assuming that the compare function implements an O(1) comparison.
Note: Creates O(n * log(n)) temporary objects that will be collected as garbage.
public func isSubset<T>(
self : Set<T>,
other : Set<T>,
compare : (implicit : (T, T) -> Order.Order)
) : BoolTest whether set1 is a sub-set of set2, i.e. each element in set1 is
also contained in set2. Returns true if both sets are equal.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set1 = Set.fromIter([1, 2].values(), Nat.compare);
let set2 = Set.fromIter([2, 1, 0].values(), Nat.compare);
let set3 = Set.fromIter([3, 4].values(), Nat.compare);
assert Set.isSubset(set1, set2, Nat.compare);
assert not Set.isSubset(set1, set3, Nat.compare);
}
Runtime: O(m * log(n)).
Space: O(1) retained memory plus garbage, see the note below.
where m and n denote the number of elements stored in the sets set1 and set2, respectively,
and assuming that the compare function implements an O(1) comparison.
public func equal<T>(
self : Set<T>,
other : Set<T>,
compare : (implicit : (T, T) -> Order.Order)
) : BoolTest whether two sets are equal. Both sets have to be constructed by the same comparison function.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set1 = Set.fromIter([1, 2].values(), Nat.compare);
let set2 = Set.fromIter([2, 1].values(), Nat.compare);
let set3 = Set.fromIter([2, 1, 0].values(), Nat.compare);
assert Set.equal(set1, set2, Nat.compare);
assert not Set.equal(set1, set3, Nat.compare);
}
Runtime: O(m * log(n)).
Space: O(1) retained memory plus garbage, see the note below.
where m and n denote the number of elements stored in the sets set1 and set2, respectively,
and assuming that the compare function implements an O(1) comparison.
public func compare<T>(
self : Set<T>,
other : Set<T>,
compare : (implicit : (T, T) -> Order.Order)
) : Order.OrderCompare two sets by comparing the elements.
Both sets must have been created by the same comparison function.
The two sets are iterated by the ascending order of their creation and
order is determined by the following rules:
Less:
set1 is less than set2 if:
element1 and element2 where
element1 is less than element2 and all preceding elements are equal, or,set1 is a strict prefix of set2, i.e. set2 has more elements than set1
and all elements of set1 occur at the beginning of iteration set2.
Equal:
set1 and set2 have same series of equal elements by pairwise iteration.
Greater:
set1 is neither less nor equal set2.Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set1 = Set.fromIter([0, 1].values(), Nat.compare);
let set2 = Set.fromIter([0, 2].values(), Nat.compare);
assert Set.compare(set1, set2, Nat.compare) == #less;
assert Set.compare(set1, set1, Nat.compare) == #equal;
assert Set.compare(set2, set1, Nat.compare) == #greater;
}
Runtime: O(n).
Space: O(1) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set and
assuming that compare has runtime and space costs of O(1).
Note: Creates O(log(n)) temporary objects that will be collected as garbage.
public func values<T>(self : Set<T>) : Iter.Iter<T>Returns an iterator over the elements in the set, traversing the elements in the ascending order.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter([0, 2, 3, 1].values(), Nat.compare);
var text = "";
for (number in Set.values(set)) {
text #= " " # Nat.toText(number);
};
assert text == " 0 1 2 3";
}Cost of iteration over all elements:
Runtime: O(n).
Space: O(1) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set.
Note: Creates O(log(n)) temporary objects that will be collected as garbage.
public func reverseValues<T>(self : Set<T>) : Iter.Iter<T>Returns an iterator over the elements in the set, traversing the elements in the descending order.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter([0, 2, 3, 1].values(), Nat.compare);
var tmp = "";
for (number in Set.reverseValues(set)) {
tmp #= " " # Nat.toText(number);
};
assert tmp == " 3 2 1 0";
}Cost of iteration over all elements:
Runtime: O(n).
Space: O(1) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set.
Note: Creates O(log(n)) temporary objects that will be collected as garbage.
public func empty<T>() : Set<T>Create a new empty set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set = Set.empty<Nat>();
assert Iter.toArray(Set.values(set)) == [];
}
Runtime: O(1).
Space: O(1).
public func singleton<T>(element : T) : Set<T>Create a new set with a single element.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set = Set.singleton(0);
assert Iter.toArray(Set.values(set)) == [0];
}
Runtime: O(1).
Space: O(1).
public func size<T>(self : Set<T>) : NatReturn the number of elements in a set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter([0, 3, 2, 1, 3].values(), Nat.compare);
assert Set.size(set) == 4;
}
Runtime: O(1).
Space: O(1).
public func foldLeft<T, A>(
self : Set<T>,
base : A,
combine : (A, T) -> A
) : AIterate all elements in ascending order, and accumulate the elements by applying the combine function, starting from a base value.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter([0, 3, 2, 1].values(), Nat.compare);
let text = Set.foldLeft<Nat, Text>(
set,
"",
func (accumulator, element) {
accumulator # " " # Nat.toText(element)
}
);
assert text == " 0 1 2 3";
}
Runtime: O(n).
Space: O(1) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set.
public func foldRight<T, A>(
self : Set<T>,
base : A,
combine : (T, A) -> A
) : AIterate all elements in descending order, and accumulate the elements by applying the combine function, starting from a base value.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter([0, 3, 2, 1].values(), Nat.compare);
let text = Set.foldRight<Nat, Text>(
set,
"",
func (element, accumulator) {
accumulator # " " # Nat.toText(element)
}
);
assert text == " 3 2 1 0";
}
Runtime: O(n).
Space: O(1) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set.
public func isEmpty<T>(self : Set<T>) : BoolDetermines whether a set is empty.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set1 = Set.empty<Nat>();
let set2 = Set.singleton<Nat>(1);
assert Set.isEmpty(set1);
assert not Set.isEmpty(set2);
}
Runtime: O(1).
Space: O(1).
public func all<T>(self : Set<T>, predicate : T -> Bool) : BoolCheck whether all element in the set satisfy a predicate, i.e.
the predicate function returns true for all elements in the set.
Returns true for an empty set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter<Nat>([0, 3, 1, 2].values(), Nat.compare);
let belowTen = Set.all<Nat>(set, func (number) {
number < 10
});
assert belowTen;
}
Runtime: O(n).
Space: O(1).
where n denotes the number of elements stored in the set.
public func any<T>(self : Set<T>, pred : T -> Bool) : BoolCheck whether at least one element in the set satisfies a predicate, i.e.
the predicate function returns true for at least one element in the set.
Returns false for an empty set.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
persistent actor {
let set = Set.fromIter<Nat>([0, 3, 1, 2].values(), Nat.compare);
let aboveTen = Set.any<Nat>(set, func (number) {
number > 10
});
assert not aboveTen;
}
Runtime: O(n).
Space: O(1).
public func assertValid<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order)) : ()Test helper that check internal invariant for the given set s.
Raise an error (for a stack trace) if invariants are violated.
public func toText<T>(self : Set<T>, elementFormat : (implicit : (toText : T -> Text))) : TextGenerate a textual representation of all the elements in the set.
Primarily to be used for testing and debugging.
The elements are formatted according to elementFormat.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set = Set.fromIter<Nat>([0, 3, 1, 2].values(), Nat.compare);
assert Set.toText(set, Nat.toText) == "PureSet{0, 1, 2, 3}";
}
Runtime: O(n).
Space: O(n) retained memory plus garbage, see below.
where n denotes the number of elements stored in the set and
assuming that elementFormat has runtime and space costs of O(1).
Note: Creates O(log(n)) temporary objects that will be collected as garbage.
public func flatten<T>(self : Set<Set<T>>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>Construct the union of a set of element sets, i.e. all elements of each element set are included in the result set. Any duplicates are ignored, i.e. if the same element occurs in multiple element sets, it only occurs once in the result set.
Assumes all sets are ordered by compare.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Order "mo:core/Order";
import Iter "mo:core/Iter";
persistent actor {
func setCompare(first: Set.Set<Nat>, second: Set.Set<Nat>) : Order.Order {
Set.compare(first, second, Nat.compare)
};
let set1 = Set.fromIter([1, 2, 3].values(), Nat.compare);
let set2 = Set.fromIter([3, 4, 5].values(), Nat.compare);
let set3 = Set.fromIter([5, 6, 7].values(), Nat.compare);
let setOfSets = Set.fromIter([set1, set2, set3].values(), setCompare);
let flatSet = Set.flatten(setOfSets, Nat.compare);
assert Iter.toArray(Set.values(flatSet)) == [1, 2, 3, 4, 5, 6, 7];
}
Runtime: O(n * log(n)).
Space: O(1) retained memory plus garbage, see the note below.
where n denotes the number of elements stored in all the sub-sets,
and assuming that the compare function implements an O(1) comparison.
public func join<T>(self : Iter.Iter<Set<T>>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>Construct the union of a series of sets, i.e. all elements of each set are included in the result set. Any duplicates are ignored, i.e. if an element occurs in several of the iterated sets, it only occurs once in the result set.
Assumes all sets are ordered by compare.
Example:
import Set "mo:core/pure/Set";
import Nat "mo:core/Nat";
import Iter "mo:core/Iter";
persistent actor {
let set1 = Set.fromIter([1, 2, 3].values(), Nat.compare);
let set2 = Set.fromIter([3, 4, 5].values(), Nat.compare);
let set3 = Set.fromIter([5, 6, 7].values(), Nat.compare);
let combined = Set.join([set1, set2, set3].values(), Nat.compare);
assert Iter.toArray(Set.values(combined)) == [1, 2, 3, 4, 5, 6, 7];
}
Runtime: O(n * log(n)).
Space: O(1) retained memory plus garbage, see the note below.
where n denotes the number of elements stored in the iterated sets,
and assuming that the compare function implements an O(1) comparison.