superhash.js
var mkhash = require('multikey-hash');
/**
* Creates a new SuperHash
*
* Example `entries` Array
*
* ```
* [[1,2,3],'foo'], [[{foo: 'bar', {blip:'blop'}],'bar']]
* ```
*
* @class
* @param {Array} entries two dimensional array with entries to prefill the map. Keys must be an array (even if just one)
* @api public
*/
function SuperHash(entries) {
var args;
this.store = {};
this.size = 0;
if (Object.defineProperty) {
Object.defineProperty(this, 'store', {enumerable:false});
}
if (!entries) {
return;
}
for (var i = 0; i < entries.length; i++) {
args = entries[i][0];
args.push(entries[i][1]);
this.set.apply(this, args);
}
}
/**
* Creates a hash from the keys if it doesn't exist and sets the last argument passed in as the value
*
* @param {...*} keys Used to generate hash
* @param {*} value to be associated with the key
* @return {Number} the hash associated with the keys
* @api public
*/
SuperHash.prototype.set = function set() {
var len = arguments.length;
var value = arguments[len-1];
var keys = new Array(len-1);
var hash;
for (var i = 0; i < len-1; i++) {
keys[i] = arguments[i];
}
hash = mkhash.apply(this, keys);
if (!this.store.hasOwnProperty(hash)) {
this.size++;
}
this.store[hash] = [keys, value];
return this;
};
/**
* Returns the value associated with the hash generated from the keys
*
* @param {...*} keys Used to generate a hash for lookup
* @return {Object} value associated with generated hash
* @api public
*/
SuperHash.prototype.get = function get() {
var hash = mkhash.apply(this, arguments);
return this.store[hash] ? this.store[hash][1] : undefined;
};
/**
* Tells whether or not value associated with the hash generated from the keys is in the map
*
* @param {...*} keys - Used to generate a hash for lookup
* @return {Boolean} true if generated hash is in the map
* @api public
*/
SuperHash.prototype.has = function has() {
var key = mkhash.apply(this, arguments);
return key in this.store;
};
/**
* Returns all keys from the hash map
* @return {Array} keys from the hash map
* @api public
*/
SuperHash.prototype.keys = function keys() {
return _getEntries(this.store, 0);
};
/**
* Returns all entries (key/value pairs) from the hash map
* @return {Array} entries from the hash map
* @api public
*/
SuperHash.prototype.entries = function entries() {
return _getEntries(this.store);
};
/**
* Returns all values from the hash map
* @return {Array} values from the hash map
* @api public
*/
SuperHash.prototype.values = function values() {
return _getEntries(this.store, 1);
};
/**
* Loops through each value in the hashmap passing it as the first argument in callack
*
* ```js
* hashMap.forEach(function(value){
*
* });
* ```
*
* @param {Function} cb callback function called with `(key, value)` for each entry in the map
* @param {*} context `this` context for the callback
* @api public
*/
SuperHash.prototype.forEach = function forEach(cb, thisArg) {
thisArg = thisArg || this;
for (var hash in this.store) {
if (this.store.hasOwnProperty(hash)) {
cb.call(thisArg, this.store[hash][1], this.store[hash][0]);
}
}
};
/**
* Removes the hash generated by the keys and the associated value
*
* @param {...*} keys - Used to generate a hash for lookup
* @return {Boolean} whether the hash existed or not
* @api public
*/
SuperHash.prototype.delete = function() {
var key = mkhash.apply(this, arguments);
if (!this.store.hasOwnProperty(key)) {
return false;
}
delete this.store[key];
this.size--;
return true;
};
/**
* Deletes all keys and values from hash map
* @api public
*/
SuperHash.prototype.clear = function clear() {
this.store = {};
this.size = 0;
};
/**
* Returns all keys, values, or entries from hash map depending on entryIndex
* @param {Object} store object of all hash/values
* @param {Number} entryIndex 0=key, 1=value, undefined=entire entry
* @return {Array} values from store
* @api private
*/
function _getEntries(store, entryIndex) {
var results = [];
var value;
var entry;
for (var hash in store) {
if (!store.hasOwnProperty(hash)){
continue;
}
entry = store[hash];
value = entryIndex === undefined ? entry : entry[entryIndex];
results.push(value);
}
return results;
}
module.exports = SuperHash;