Is there any way to create Set data structure(Unique Collections) like java in javascript?
5 Answers 5
For a set of strings, I would just use a object with the value true.
var obj = {};
obj["foo"] = true;
obj["bar"] = true;
if(obj["foo"])
{
// foo in set
}
This is basically how HashSet works in Java, assuming the JavaScript object is implemented as a hashtable (which is typical).
-
So how to remove an object from that set? obj["foo"]=null? or obj["foo"]=false?Eran Medan– Eran Medan2011年04月05日 13:47:51 +00:00Commented Apr 5, 2011 at 13:47
-
8@Eran,
delete obj["foo"]
ordelete obj.foo
.Matthew Flaschen– Matthew Flaschen2011年04月05日 13:53:37 +00:00Commented Apr 5, 2011 at 13:53 -
Thanks for teaching an old dog a new trick :) this is amazing I never encountered it in JS, brings me back to my C++ days though...Eran Medan– Eran Medan2011年04月05日 16:18:08 +00:00Commented Apr 5, 2011 at 16:18
-
@Eran, yeah. As you probably know, it's quite different in JavaScript, given that it's garbage-collected and there are no destructors.Matthew Flaschen– Matthew Flaschen2011年04月05日 19:23:31 +00:00Commented Apr 5, 2011 at 19:23
I have written a JavaScript implementation of a hash set that is similar to Java's HashSet. It allows any object (not just strings) to be used as a set member. It's based on the keys of a hash table.
http://code.google.com/p/jshashtable/downloads/list
Documentation will follow shortly, I promise. For now, the source should give you the API pretty clearly, and here's an example:
var s = new HashSet();
var o1 = {name: "One"}, o2 = {name: "Two"};
s.add(o1);
s.add(o2);
s.add(o2);
s.values(); // Array containing o1 and a single reference to o2
Well though it seemed to be a common problem, and I found what seemed to be a good Set class on the net that supports objects, I wanted a simpler one and ended up writing one myself... in case anyone else finds it useful...
/**
* A Javascript Class that represents a set of unique values
*
* Usage:
*
* var s = new jsSet();
*
* s.add('a1'); s.add('a2');
*
* s.list(); >> ['a1','a2']
*
* s.remove('a1'); s.list(); >> ['a2']
*
* s.contains('a1') >> false
*
* s.contains('a2') >> true
*
* can be chained
* s.add(null).add('hello');
*
* add array
* s.addAll([ null, 'a', 'b' ]);
*
* remove array
* s.addAll([ null, 'a', 'b' ]);
*
* retrieve the elements as a list
* s.list();
*
* size of the set
* s.size();
*
*/
function jsSet() {
// null can also be an element of the set, but needs
// a separate indication to differentiate it from
// the string "null" as well
this.isNullAdded = false;
// private member variable hence no 'this'
var map = {};
// Scope for optimization
// could be cached instead of generating each time
// this.uniqueList = [];
// returns true if the element is in this set, false otherwise
this.contains = function(key) {
if (key === null)
return this.isNullAdded;
else if (key === undefined)
return false;
else
return map[key] ? true : false;
};
// adds the element to the set
this.add = function(val) {
if (val === null)
this.isNullAdded = true;
else if (val !== undefined)
map[val] = true;
return this;
};
// adds all the elements of the array to the set
this.addAll = function(val) {
if (val !== null && val !== undefined && val instanceof Array) {
for ( var idx = 0; idx < val.length; idx++) {
this.add(val[idx]);
}
}
return this;
};
// removes the specified element from the set
this.remove = function(val) {
if (val === null)
this.isNullAdded = false;
else if (val !== undefined)
delete map[val];
return this;
};
// removes all the element in the array from the set
this.removeAll = function(val) {
if (val !== null && val !== undefined && val instanceof Array) {
for ( var idx = 0; idx < val.length; idx++) {
console.log('val: %s:%s', idx, val[idx]);
this.remove(val[idx]);
}
}
return this;
};
// empties the set of all values
this.clear = function() {
this.isNullAdded = false;
map = {};
return this;
};
// returns the number of elements in the set
this.size = function() {
return this.list().length;
};
// returns true if the set is empty, false otherwise
this.isEmpty = function() {
return this.list().length > 0? false: true;
};
// returns the elements of the set as a list
this.list = function() {
var arr = [];
if (this.isNullAdded)
arr.push(null);
for (o in map) {
// protect from inherited properties such as
// Object.prototype.test = 'inherited property';
if (map.hasOwnProperty(o))
arr.push(o);
}
return arr;
};
};
-
if we don't need null values in the Set, then we can just do a remove(null) after adding all elements.msanjay– msanjay2011年11月04日 11:40:33 +00:00Commented Nov 4, 2011 at 11:40
In modern browsers, I would use a Map using only the keys' methods. For example:
- New set:
let mySet = new Map();
- Add element:
mySet.set(element, 1)
- Remove element:
mySet.delete(element)
- Contains element:
mySet.has(element)
You can make your own wrapper if you don't want to see the Map implementation. This approach is how Java HashSet is implemented, it uses a HashMap and only uses the key methods.
Javascript now provides (part of es6) Set
Api, which can be used to create unique collection.
var set = new Set([1,1,2,3]);
set.add(1);
set.add(4);
For more info, visit - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set