Sets are unordered collections of objects. Like arrays, a set is enumerable. Unlike arrays, sets are very fast at determining membership. This makes sets ideal anytime you need to keep track of which objects belong to a particular group, but you don't care especially about the order of those items.
Sets are very fast and memory efficient. Do not hesitate to use them instead of arrays when you don't care about the order of a collection.
SproutCore Runtime comes with several Set-like objects optimized for handling different types of content. All set objects implement the SC.Enumerable API, however. This means you can easily iterate through items using any of the provided iterators. You can also easily convert a set into an array and vice-versa.
This section describes the different types of sets provided by SproutCore.
SC.Set: Collections of Objects
SC.Set is the most general type of collection provided by SproutCore. You can use a set to store any type of object, including numbers, strings, and so on. Runtime also defines a close cousin to SC.Set called SC.CoreSet. SC.CoreSet does not support property observing, which makes it a bit faster and more memory efficient.
Usually you should use SC.Set anytime you want to set the object as a public property. Use SC.CoreSet for private variables where you won't use property observing and performance in paramount.
Creating a Set
To create a set, simply use the create() method. You can also copy an existing set:
var setA = SC.Set.create(); // new empty set
var setB = setA.copy(); // returns a new copy
Adding and Removing Items
To add to or remove from a set, use the add() and remove() methods. Both methods return the set itself so you can chain them. You can also add objects of different types:
var setA = SC.Set.create();
setA.add(object1).add("foo"); // set contains object1 and "foo"
setB.remove(object1); // set contains only "foo"
You can only add() an item to the set once. If you try to add an item to a set that is already in the set, add() will do nothing. Likewise, if you try to remove() and item that is not in the set, it will have no effect:
var setA = SC.Set.create();
setA.add('foo').add('foo');
setA.get('length'); => 1 // only added once
setA.remove('bar');
setA.get('length') => 1 // no change
If you want to add or remove all the items from another SC.Enumerable (including an Array or another Set), use addEach() or removeEach():
var array1 = [1,2,3], array2 = [2,3];
var setA = SC.Set.create();
setA.addEach(array1); // set is now {1,2,3}
setA.removeEach(array2); // set is now {1}
You can also remove all items from a set using the clear() method. This will remove all items in a very efficient way.
Checking Length
Like all enumerables, SC.Set has a length property that will tell you how many items are in the set:
var setA = SC.Set.create();
setA.get('length'); => 0
setA.add('foo');
setA.get('length') => 1
setA.remove('foo');
setA.get('length') => 0
Testing For Membership
One of the primary reasons you might use a Set is to keep track of object membership. You can test for membership using the contains() method:
var setA = SC.Set.create().add('foo');
setA.contains('foo') => true
setA.contains('bar') => false
Note that SC.Set tests for objects using ===. This means that if you pass a separate instance of the same object or array to a set, they will not match even though their internal state might be the same:
var array1 = [1,2,3], array2 = [1,2,3];
var setA = SC.Set.create().add(array);
setA.contains(array1); => true // same instance
setA.contains(array2); => false // different instance
If you want to control this behavior for a custom object, you can always implement the hash() method on your object. This method should return a string representing the object's internal state. Two objects that return the same hash value will be treated as equivalent.
Fetching Objects
Finally, to fetch objects from a set, you should use the standard iterators defined by SC.Enumerable such as forEach:
var set = SC.Set.create().addEach([1,2,3]);
set.forEach(function(x) {
console.log(x);
});
=> 1
=> 2
=> 3
Many times, you just want to get a single object from the set. This is especially true if you expect the set to contain only one object most of the time. For this purpose you can use the firstObject property:
var set = SC.Set.create().addEach([1,2,3]);
set.get('firstObject') => returns one of 1, 2, or 3
Note that because Sets are unordered, firstObject may return any item in the set. Only use firstObject when you want to get a single object from the set and you truly do not care which one it is. If you want to fetch a specific item from the set, you could use find() instead [defined on SC.Enumerable]:
var set = SC.Set.create().addEach([1,2,3]);
set.find(function(x) { return x > 2; }); // returns 3
Finally, sometimes sets are used as an unordered queue of objects. If you just want to retrieve an item from the test and remove that item at the same time, use the pop() method:
var set = SC.Set.create().addEach([1,2,3]);
set.pop(); // returns 1 - set is now {2,3}
set.pop(); // returns 2 - set is now {3}
Again, remember that the order of a set is not guaranteed. pop() may return objects in any order.
Other Types of Sets
SproutCore also includes some close cousins of SC.Set including SC.IndexSet and SC.SelectionSet:
Moving On
Learn more about the IndexSet, SelectionSet or
return to Runtime Programming Guide Home ยป
Comments (0)
You don't have permission to comment on this page.