esco/superhash

View on GitHub
superhash.js

Summary

Maintainability
A
0 mins
Test Coverage
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;