Set

The Set class can be used to model collections of unique objects. A set makes sure that there are no duplicates among its members, and it allows you to use custom equality methods for comparison as well as JavaScript’s === operator.

// In the browser
JS.require('JS.Set', function(Set) { ... });

// In CommonJS
var Set = require('jsclass/src/set').Set;

There are actuall three set classes available; all have the same API but have different storage mechanisms. They are:

If you try to add an object that has equals() and hash() methods to a set, those methods will be used to compare the object to the set’s members. equals() should accept one argument and return a boolean to indicate whether the two objects are to be considered equal. If no equals() method exists on the object, the === operator is used instead. An example class might look like:

Widget = new Class({
    initialize: function(name) {
        this.name = name;
    },
    equals: function(object) {
        return (object instanceof this.klass)
            && object.name == this.name;
    },
    hash: function() {
        return this.name;
    }
});

Although JavaScript’s built-in Array and Object classes do not have an equals() method, the Set classes can detect when two such objects are equal. So, you cannot put two arrays with the same elements into a set together.

Bear in mind that uniqueness (and sort order for SortedSet) is only maintained when new objects are added to the set. Objects can be changed such that two objects that are unequal can be made to be equal; if those two objects are members of a set the set is then corrupted. To get around this, all sets have a rebuild() method that throws out any duplicates and fixes sort order.

Creating a set is simple: simply pass an array (or some other enumerable object) with the data to put in the set:

var evensUnderTen = new Set([2,4,6,8]);

Set and SortedSet include the Enumerable module. The iteration order for Set is arbitrary and is not guaranteed, whereas for SortedSet iteration takes place in sort order. The rest of the API is as follows. As a general rule, any method that returns a new set will return a set of the same type as the receiver, i.e. if set is a Set then set.union(other) returns a new Set, if set is a SortedSet the same call returns a SortedSet.

add(item)

Adds a new item to the set as long as the set does not already contain the item. If item has an equals() method, item.equals() is used for comparison to other set members (see above). Returns a boolean to indicate whether or not the item was added.

var evensUnderTen = new Set([2,4,6,8]);
evensUnderTen.add(6)    // -> false
evensUnderTen.add(0)    // -> true

classify(block, context)

Splits the set into several sets based on the return value of block for each member, returning a Hash whose keys are the distinct return values.

// Classify by remainder when divided by 3

var s = new Set([1,2,3,4,5,6,7,8,9]);
var c = s.classify(function(x) { return x % 3 });

// c.get(0) == Set{3,6,9}
// c.get(1) == Set{1,4,7}
// c.get(2) == Set{2,5,8}

clear()

Removes all members from the set.

complement(other)

Returns a new set containing all the members of other that are not in the receiver.

contains(item)

Returns true iff the set contains item.

difference(other)

Returns a new set containing all the members of the receiver that are not in the set other.

var a = new Set([1,2,3,4,5,6,7,8,9]);
var b = new Set([2,4,6,8]);

a.difference(b)
// -> Set{1,3,5,7,9}

divide(block, context)

Similar to classify(block, context) except that the result is given as a set of sets, rather than as key/value pairs.

// Classify by remainder when divided by 3

var s = new Set([1,2,3,4,5,6,7,8,9]);
var c = s.divide(function(x) { return x % 3 });

// c == Set { Set{3,6,9}, Set{1,4,7}, Set{2,5,8} }

equals(set)

Returns true iff set is a Set or a SortedSet with the same members as the receiver.

flatten()

Flattens the set in place, such that any sets nested within the receiver are merged and their members become the receiver’s members.

var s = new Set([ new Set([3,9,4]), new Set([1,7,3,5]), 3, 7 ]);

// s == Set{ Set{3,9,4}, Set{1,7,3,5}, 3, 7}

s.flatten();

// s == Set{3,9,4,1,7,5}

intersection(set)

Returns a new set containing members common to both set and the receiver.

isEmpty()

Returns true iff the receiver has no members.

isProperSubset(other)

Returns true iff the receiver is a proper subset of the set other, that is if all the members of the receiver are also in other, and the receiver is a smaller set than other.

isProperSuperset(other)

Returns true iff the receiver is a proper superset of the set other, that is if all the members of other are also in the receiver, and the receiver is a larger set than other.

isSubset(other)

Returns true iff the receiver is a subset of the set other, that is if all the members of the receiver are also members of other.

isSuperset(other)

Returns true iff the receiver is a superset of the set other, that is if all the members of other are also members of the receiver.

keepIf(predicate, context)

Removes all the members of the set for which predicate returns false.

var s = new Set([1,2,3,4,5,6,7,8,9]);

// Keep multiples of 3
s.keepIf(function(x) { return x % 3 == 0 });

// s == Set{3,6,9}

merge(set)

Adds all the members of set to the receiver.

product(set)

Returns a new (always non-sorted) set of all possible ordered pairs whose first member is in the receiver and whose second member is in set.

var a = new Set([1,2]), b = new Set([3,4]);
var prod = a.product(b);

// prod == Set{ [1,3], [1,4], [2,3], [2,4] }

rebuild()

Acts as an integrity check on the receiver. If some of the objects in the set have changed such that they are now equal then any duplicates are discarded. For SortedSet instances, this also sorts the set if any objects have changed such that they are now in the wrong position.

remove(item)

Removes the member item (i.e. whichever member is equal to item) from the receiver.

removeIf(predicate, context)

Removes all the members of the set for which predicate returns true.

var s = new Set([1,2,3,4,5,6,7,8,9]);

// Remove multiples of 3
s.removeIf(function(x) { return x % 3 == 0 });

// s == Set{1,2,4,5,7,8}

replace(other)

Removes all the members from the receiver and replaces them with those of the set other.

subtract(list)

Removes all the members of list from the receiver. This is similar to difference, except that it modifies the receiving set in place rather than returning a new set.

union(set)

Returns a new set containing all the members from set and the receiver.

xor(other)

Returns a new set containing members that are either in other or in the receiver, but not in both. This is equivalent to:

// a.xor(b) ->
(a.union(b)).difference(a.intersection(b))