Sets

2018-03-16

Sets is a sequential data structure that does not allow duplicated values.

Sets

ES5: Creating a set:

  • The Skeleton of our Set class:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Set(){
    let items = {};
    this.add = function (value){};
    this.delete = function(value){};
    this.has = function(value){};
    this.clear = function(){};
    this.size = function(){};
    this.values = function(){};
    }
  • The has(value) method

    1
    2
    3
    4
    5
    6
    7
    this.has = function(value) {
    return value in items;
    };
    // A better way of implementing this method
    this.has = function (value) {
    return items.hasOwnProperty(value); // return false if the property is inherited from prototype
    }
  • The add() method

    1
    2
    3
    4
    5
    6
    7
    this.add = function(value){
    if(!this.has(value)){
    items[value] = value; // we are adding the value as key and value because it will help us search for the value if we store it as the key as well
    return true;
    }
    return false;
    }
  • The delete() and clear() methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    this.delete = function(value){
    if (this.has(value)){
    delete items[value];
    return true;
    }
    return false;
    }
    this.clear = function() {
    items = {};
    }
  • The size() method

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // three methods to implement the size method
    // First
    function Set() {
    let items = {};
    let length = 0;
    this.add(value) {
    // omit code
    length ++;
    }
    this.remove(value){
    // omit code
    length --;
    }
    }
    // Second
    this.size = function() {
    return Object.keys(items).length;
    }
    // Third
    this.sizeLegacy = function(){
    let count = 0;
    for (let key in items){
    if(items.hasOwnProperty(key))
    ++ count;
    }
    return count;
    }
    // We cannot simply use the for-in statement to iterate through the properties of the items object, because the object'prototype contains aadditional properties for the object.
  • The values() method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// work in modern browsers
this.values = function(){
let values = [];
for( let i = 0, key = Object.keys(items); i < keys.length; i++ ){
values.push(items[key[i]]);
}
return values;
}
// work in any browser
this.valuesLegacy = function(){
let values = [];
for(let key in items){
if(items.hasOwnProperty(key)){
values.push(items[key]);
}
}
return values;
}
  • The final version
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    function Set() {
    let items = {};
    this.has = function(value){
    return items.hasOwnProperty(value);
    }
    this.add = function(value){
    if(!this.has(value)){
    items[value] = value;
    return true;
    }
    return false;
    }
    this.delete = function(value){
    if(this.has(value)){
    delete items[value];
    return true;
    }
    return false;
    }
    this.clear = function(){
    let items = {};
    }
    this.size = function(){
    return Object.keys(items).length;
    }
    this.values = function(){
    let values = [];
    for(let i = 0, key = Object.keys(items); i < key.length; i ++){
    values.push(items[key[i]]);
    }
    return values;
    }
    }

Set Opeation:

  • Set Union
1
2
3
4
5
6
7
8
9
10
11
12
13
14

this.union = function(otherSet){
let unionSet = new Set();

let values = this.values();
for ( let i = 0; i < values.length; i ++ ){
unionSet.add(values[i]);
}
values = otherSet.values();
for ( let i = 0; i < values.length; i++ ){
unionSet.add(values[i]);
}
return unionSet;
}
  • Set intersection
1
2
3
4
5
6
7
8
9
10
11
this.intersection = function(oterhSet) {
let intersectionSet = new Set();

let values = this.values();
for( let i = 0; i < values.legnth; i++ ){
if ( otherSet.has(values[i])){
intersectionSet.add(values[i]);
}
}
return intersectionSet;
}
  • Set difference

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    this.difference = function(otherSet) {
    let differenceSet = new Set();

    let values = this.values();

    for ( let i = 0; i < values.length; i++ ){
    if( !otherSet.has(values[i])) {
    differenceSet.add(values[i]);
    }
    }
    return differenceSet;
    }
  • Subset

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    this.subset = function(otherSet) {
    if ( this.size() > otherSet.size() ){
    return false;
    } else {
    let values = this.values();
    for (let i = 0; i < values.length; i++ ){
    if ( !otherSet.has(values[i])){
    return false;
    }
    }
    return true;
    }
    }

ES6-the Set class

  • The difference between our Set class and the ES6 Set class is that the values method returns Iterator instead of the array with the values.
  • In ES6 Set class instance, the size is a propery rather than a method.
  • ES6 native Set class does not contain common set operation such as Union, Intersection.
  • Simulating the union operation
1
2
3
let unionAb = new Set();
for ( let x of SetA ) unionAb.add(x);
for ( let x of SetB ) unionAb.add(x);
  • Simulating the intersection operation
1
2
3
4
5
6
7
8
9
10
11
12
13
let intersection = function(setA, setB){
let intersectionSet = new Set();
for (let x of setA){
if (setB.has(x)){
intersectionSet.add(x);
}
}
return intersectionSet;
};

let intersectionAB = intersection(setA, setB);
// A simpler version
let intersectionAB = new Set([x for (x of setA) if (setB.has(x)]));
  • Simulating the difference operation
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let difference = function(setA, setB){
    let differenceSet = new Set();
    for (let x of setA){
    if (!setB.has(x)){
    differenceSet.add(x);
    }
    }
    return differenceSet;
    };
    // A simpler version

    let differenceSet = new Set([x for (x of setA) if (!setB.has(x))]);
    // Firefox is the only broswer that supports simplified syntax code.