Javascript Set

As Most of the Javascript Set implementations have flaw in comparing objects, as javascript  compares identities of the objects, not actual values. Here is my implementation with true   object  value comparison.
/*Constructor: Takes array or implicit null as an argument*/
function Set(arr)
{
if(arr == null)
this._array =
[];
else
{
if(arr.constructor == Array)
this._array = arr;
else
this._array = [arr];
}
}

Set.prototype =
{
/*Compares the type of the objects and actual values, rather than object identity*/
_compare : function(i, j )
{
var itype = typeof(i);
var jtype = typeof(j);

/*Both are primitives, compare directly*/
if(itype != 'object' && jtype != 'object')
return i === j;

/*Both are objects*/
if(itype == 'object' && jtype == 'object')
{
if(i.constructor != j.constructor) /*Check whether, they are of same type */
return false;

for(var k in i) /*For each value compare recursively*/
{
if(! k in j || !this._compare(i[k], j[k])) return false;
}
return true;
}

/*comparison of primitive form and object form*/
if(itype == 'object')
return i.valueOf() === j;

return i === j.valueOf();
},

/*Returns values of the set*/
values: function()
{
return this._array;
},

/*Returns the size of the set*/
size : function()
{
return this._array.length;
},

/*Checks whether Set has an element or not*/
contains : function(n)
{
for(var i in this._array)
{
if(this._compare(this._array[i], n) )
return true;
}

return false;
},


/*adds the element to the set, if it is not there */
add: function(n)
{
if(!this.contains(n))
this._array.push(n);
},


/*removes the element from the set, if it is there*/
remove: function(n)
{
for(var i in this._array)
{
if(this._compare(this._array[i], n) )
{
this._array.splice(i, 1);
return;
}
}
},

/*Returns new set containing union of the two*/
union: function(other)
{
var result;
var arr;

if(this.size() > other.size())
{
result = new Set( this._array.slice(0) );
arr = other._array;

}
else
{
result = new Set(other._array.slice(0));
arr = this._array;

}

for(var i in arr)
{
if( !result.contains(arr[i]))
result.add(arr[i]);

}

return result;
},

/*Returns new set containing intersection of the two*/
intersection: function(other)
{
var result = new Set();
var arr, set;

if(this.size() < other.size())
{
arr = this._array;
set = other;

}
else
{
arr = other._array;
set = this;

}

for(var i in arr)
{
if( set.contains(arr[i]))
result.add(arr[i]);

}

return result;
},

/*Checks this is subset of other*/
isSubsetOf: function(other)
{
for(var i in this._array)
{
if(!other.contains(this._array[i]))
return false;
}

return true;
},

/*Checks whether two sets are equal*/
equals : function(other)
{
return this.isSubsetOf(other) && other.isSubsetOf(this);
},

/*Subtracts other from this*/
minus : function(other)
{
var arr = this._array.slice(0);

for(var i in arr )
{
if(other.contains(arr[i]))
arr.splice(i, 1);
}

return new Set(arr);
}
};
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s