hash-set
Version:
Set with custom equality comparisons
177 lines (169 loc) • 6.09 kB
JavaScript
'use strict';
/**
* Returns `Set` class with custom equality comparisons.
*
* @param {function} hashFn — the function to determine the unique of value.
* @returns {HashSet}
*/
module.exports = function hashSet(hashFn) {
if (!hashFn) {
throw new Error('You should specify hash function to create HashSet.');
}
/**
* Set objects are collections of values, you can iterate its elements in insertion order.
*
* A value in the Set may only occur once; it is unique in the Set's collection.
*/
return class HashSet {
/**
* The value of the length property is 0.
*/
static get length() {
return 0;
}
/**
* Returns the function that created an instance's prototype.
*
* @param {Iterable} iterable — if an iterable object is passed, then all of its elements
* will be added to the new Set. `null` is treated as undefined.
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of}
*/
constructor(iterable) {
this._map = new Map();
if (iterable) {
for (let item of iterable) {
this.add(item);
}
}
}
/**
* The value of size is an integer representing how many entries the Set object has.
* A set accessor function for size is undefined; you can not change this property.
*
* @returns {number} the number of elements in a Set object.
*/
get size() {
return this._map.size;
}
/**
* Appends a new element with the given value to the Set object.
*
* @param {*} value — the value of the element to add to the Set object.
* @returns {HashSet}.
*/
add(value) {
const id = hashFn(value);
if (!this._map.has(id)) {
this._map.set(id, value);
}
return this;
}
/**
* Returns a boolean asserting whether an element is present with the given value in the Set object or not.
*
* @param {*} value — the value to test for presence in the Set object.
* @returns {boolean} Returns true if an element with the specified value exists in the Set object;
* otherwise false.
*/
has(value) {
const id = hashFn(value);
return this._map.has(id);
}
/**
* Removes the element associated to the value and returns the value that.
*
* `Set.prototype.has(value)` would have previously returned.
* `Set.prototype.has(value)` will return false afterwards.
*
* @param {*} value — the value of the element to remove from the Set object.
* @returns {boolean} Returns true if an element in the Set object has been removed successfully;
* otherwise false.
*/
delete(value) {
const id = hashFn(value);
return this._map.delete(id);
}
/**
* Removes all elements from the Set object.
*/
clear() {
this._map.clear();
}
/**
* Returns a new Iterator object that contains an array of [value, value] for each element in the Set object,
* in insertion order.
*
* This is kept similar to the Map object, so that each entry has the same value for its key and value here.
*
* @returns {Iterator}
*/
entries() {
return this._map.values();
}
/**
* Executes a provided function once per each value in the Set object, in insertion order.
*
* It is not invoked for values which have been deleted. However, it is executed for values which are present
* but have the value undefined.
*
* Callback is invoked with three arguments:
* * the element value
* * the element key
* * the Set object being traversed
*
* @param {function} callbackFn — function to execute for each element.
* @param {object} thisArg — value to use as this when executing callback. If a thisArg parameter is provided
* to forEach, it will be used as the this value for each callback.
*/
forEach(callbackFn, thisArg) {
this._map.forEach((value, key) => callbackFn.call(thisArg, value, key, this));
}
/**
* Returns a new Iterator object that contains the values for each element in the Set object in insertion order.
*
* Is the same function as the values() function.
*
* @returns {Iterator}
*/
values() {
return this._map.values();
}
/**
* Returns a new Iterator object that contains the values for each element in the Set object in insertion order.
*
* Is the same function as the values() function.
*
* @returns {Iterator}
*/
keys() {
return this._map.values();
}
/**
* The initial value of the @@iterator property is the same function object as the initial
* value of the values property.
*
* Is the same function as the values() function.
*
* @returns {Iterator}
*/
[Symbol.iterator]() {
return this._map.values();
}
/**
* Returns Set object is equivalent to this HashSet object.
*
* @returns {Set}
*/
valueOf() {
return new Set(this._map.values());
}
/**
* Returns a string representing object.
*
* @returns {string}
*/
toString() {
return '[object Set]';
}
};
}