Add assoc and hash helpers.

This commit is contained in:
John-David Dalton
2015-10-01 22:02:42 -07:00
parent d407d8aa08
commit b3f6426d36

230
lodash.js
View File

@@ -1316,14 +1316,14 @@
function runInContext(context) { function runInContext(context) {
context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root; context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root;
/** Native constructor references. */ /** Built-in constructor references. */
var Date = context.Date, var Date = context.Date,
Error = context.Error, Error = context.Error,
Math = context.Math, Math = context.Math,
RegExp = context.RegExp, RegExp = context.RegExp,
TypeError = context.TypeError; TypeError = context.TypeError;
/** Used for native method references. */ /** Used for built-in method references. */
var arrayProto = context.Array.prototype, var arrayProto = context.Array.prototype,
objectProto = context.Object.prototype, objectProto = context.Object.prototype,
stringProto = context.String.prototype; stringProto = context.String.prototype;
@@ -1355,14 +1355,11 @@
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
); );
/** Native value references. */ /** Built-in value references. */
var ArrayBuffer = context.ArrayBuffer, var ArrayBuffer = context.ArrayBuffer,
Map = getNative(context, 'Map'),
Reflect = context.Reflect, Reflect = context.Reflect,
Set = getNative(context, 'Set'),
Symbol = context.Symbol, Symbol = context.Symbol,
Uint8Array = context.Uint8Array, Uint8Array = context.Uint8Array,
WeakMap = getNative(context, 'WeakMap'),
clearTimeout = context.clearTimeout, clearTimeout = context.clearTimeout,
enumerate = Reflect ? Reflect.enumerate : undefined, enumerate = Reflect ? Reflect.enumerate : undefined,
getPrototypeOf = Object.getPrototypeOf, getPrototypeOf = Object.getPrototypeOf,
@@ -1374,9 +1371,8 @@
setTimeout = context.setTimeout, setTimeout = context.setTimeout,
splice = arrayProto.splice; splice = arrayProto.splice;
/* Native method references for those with the same name as other `lodash` methods. */ /* Built-in method references for those with the same name as other `lodash` methods. */
var nativeCeil = Math.ceil, var nativeCeil = Math.ceil,
nativeCreate = getNative(Object, 'create'),
nativeFloor = Math.floor, nativeFloor = Math.floor,
nativeIsFinite = context.isFinite, nativeIsFinite = context.isFinite,
nativeKeys = Object.keys, nativeKeys = Object.keys,
@@ -1385,6 +1381,12 @@
nativeParseInt = context.parseInt, nativeParseInt = context.parseInt,
nativeRandom = Math.random; nativeRandom = Math.random;
/* Built-in method references that are verified to be native. */
var Map = getNative(context, 'Map'),
Set = getNative(context, 'Set'),
WeakMap = getNative(context, 'WeakMap'),
nativeCreate = getNative(Object, 'create');
/** Used to store function metadata. */ /** Used to store function metadata. */
var metaMap = WeakMap && new WeakMap; var metaMap = WeakMap && new WeakMap;
@@ -1725,9 +1727,9 @@
*/ */
function MapCache() { function MapCache() {
this.__data__ = { this.__data__ = {
'hash': createCache(), 'hash': createHash(),
'map': (Map ? new Map : []), 'map': Map ? new Map : [],
'string': createCache() 'string': createHash()
}; };
} }
@@ -1741,27 +1743,11 @@
* @returns {boolean} Returns `true` if the entry was removed, else `false`. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/ */
function mapDelete(key) { function mapDelete(key) {
var data = this.__data__, var data = this.__data__;
map = data.map;
if (isKeyable(key)) { if (isKeyable(key)) {
var hash = typeof key == 'string' ? data.string : data.hash; return hashDelete(typeof key == 'string' ? data.string : data.hash, key);
return hasOwnProperty.call(hash, key) && delete hash[key];
} }
if (Map) { return Map ? data.map['delete'](key) : assocDelete(data.map, key);
return map['delete'](key);
}
var index = assocIndexOf(map, key);
if (index < 0) {
return false;
}
var lastIndex = map.length - 1;
if (index == lastIndex) {
map.pop();
} else {
splice.call(map, index, 1);
}
return true;
} }
/** /**
@@ -1771,21 +1757,14 @@
* @name get * @name get
* @memberOf MapCache * @memberOf MapCache
* @param {string} key The key of the value to get. * @param {string} key The key of the value to get.
* @returns {*} Returns the cached value. * @returns {*} Returns the entry value.
*/ */
function mapGet(key) { function mapGet(key) {
var data = this.__data__, var data = this.__data__;
map = data.map;
if (isKeyable(key)) { if (isKeyable(key)) {
var hash = typeof key == 'string' ? data.string : data.hash; return hashGet(typeof key == 'string' ? data.string : data.hash, key);
return (nativeCreate || hasOwnProperty.call(hash, key)) ? hash[key] : undefined;
} }
if (Map) { return Map ? data.map.get(key) : assocGet(data.map, key);
return map.get(key);
}
var index = assocIndexOf(map, key);
return index < 0 ? undefined : map[index][1];
} }
/** /**
@@ -1798,18 +1777,15 @@
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/ */
function mapHas(key) { function mapHas(key) {
var data = this.__data__, var data = this.__data__;
map = data.map;
if (isKeyable(key)) { if (isKeyable(key)) {
var hash = typeof key == 'string' ? data.string : data.hash; return hashHas(typeof key == 'string' ? data.string : data.hash, key);
return hasOwnProperty.call(hash, key);
} }
return Map ? map.has(key) : (assocIndexOf(map, key) > -1); return Map ? data.map.has(key) : assocHas(data.map, key);
} }
/** /**
* Sets `value` to `key` of the map. * Sets the map `key` to `value`.
* *
* @private * @private
* @name set * @name set
@@ -1819,23 +1795,13 @@
* @returns {Object} Returns the map cache object. * @returns {Object} Returns the map cache object.
*/ */
function mapSet(key, value) { function mapSet(key, value) {
var data = this.__data__, var data = this.__data__;
map = data.map;
if (isKeyable(key)) { if (isKeyable(key)) {
var hash = typeof key == 'string' ? data.string : data.hash; hashSet(typeof key == 'string' ? data.string : data.hash, key, value);
hash[key] = value; } else if (Map) {
} data.map.set(key, value);
else if (Map) { } else {
map.set(key, value); assocSet(data.map, key, value);
}
else {
var index = assocIndexOf(map, key);
if (index < 0) {
map.push([key, value]);
} else {
map[index][1] = value;
}
} }
return this; return this;
} }
@@ -1885,6 +1851,70 @@
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/**
* Removes `key` and its value from the associative array.
*
* @private
* @param {Array} array The array to query.
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
function assocDelete(array, key) {
var index = assocIndexOf(array, key);
if (index < 0) {
return false;
}
var lastIndex = array.length - 1;
if (index == lastIndex) {
array.pop();
} else {
splice.call(array, index, 1);
}
return true;
}
/**
* Gets the associative array value for `key`.
*
* @private
* @param {Array} array The array to query.
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
function assocGet(array, key) {
var index = assocIndexOf(array, key);
return index < 0 ? undefined : array[index][1];
}
/**
* Checks if an associative array value for `key` exists.
*
* @private
* @param {Array} array The array to query.
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
function assocHas(array, key) {
return assocIndexOf(array, key) > -1;
}
/**
* Sets the associative array `key` to `value`.
*
* @private
* @param {Array} array The array to modify.
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
*/
function assocSet(array, key, value) {
var index = assocIndexOf(array, key);
if (index < 0) {
array.push([key, value]);
} else {
array[index][1] = value;
}
}
/** /**
* The base implementation of `_.assign` without support for multiple sources * The base implementation of `_.assign` without support for multiple sources
* or `customizer` functions. * or `customizer` functions.
@@ -2289,7 +2319,7 @@
* @private * @private
* @param {Object} object The object to query. * @param {Object} object The object to query.
* @param {Array|string} key The key to check. * @param {Array|string} key The key to check.
* @returns {boolean} Returns `true` if `key` is a property, else `false`. * @returns {boolean} Returns `true` if `key` exists, else `false`.
*/ */
function baseHas(object, key) { function baseHas(object, key) {
return object != null && hasOwnProperty.call(object, key); return object != null && hasOwnProperty.call(object, key);
@@ -2301,7 +2331,7 @@
* @private * @private
* @param {Object} object The object to query. * @param {Object} object The object to query.
* @param {Array|string} key The key to check. * @param {Array|string} key The key to check.
* @returns {boolean} Returns `true` if `key` is a property, else `false`. * @returns {boolean} Returns `true` if `key` exists, else `false`.
*/ */
function baseHasIn(object, key) { function baseHasIn(object, key) {
return object != null && key in Object(object); return object != null && key in Object(object);
@@ -3424,16 +3454,6 @@
return wrapper; return wrapper;
} }
/**
* Creates an empty cache object.
*
* @private
* @returns {Object} Returns the new cache object.
*/
function createCache() {
return nativeCreate ? nativeCreate(null) : {};
}
/** /**
* Creates a function like `_.camelCase`. * Creates a function like `_.camelCase`.
* *
@@ -3535,6 +3555,16 @@
}; };
} }
/**
* Creates an hash object.
*
* @private
* @returns {Object} Returns the new hash object.
*/
function createHash() {
return nativeCreate ? nativeCreate(null) : {};
}
/** /**
* Creates a function that wraps `func` and invokes it with optional `this` * Creates a function that wraps `func` and invokes it with optional `this`
* binding of, partial application, and currying. * binding of, partial application, and currying.
@@ -4129,6 +4159,54 @@
return { 'start': start, 'end': end }; return { 'start': start, 'end': end };
} }
/**
* Removes `key` and its value from the hash.
*
* @private
* @param {Object} hash The hash to modify.
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
function hashDelete(hash, key) {
return (nativeCreate ? key in hash : hasOwnProperty.call(hash, key)) && delete hash[key];
}
/**
* Gets the hash value for `key`.
*
* @private
* @param {Object} hash The hash to query.
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
function hashGet(hash, key) {
return (nativeCreate || hasOwnProperty.call(hash, key)) ? hash[key] : undefined;
}
/**
* Checks if a hash value for `key` exists.
*
* @private
* @param {Object} hash The hash to query.
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
function hashHas(hash, key) {
return nativeCreate ? key in hash : hasOwnProperty.call(hash, key);
}
/**
* Sets the hash `key` to `value`.
*
* @private
* @param {Object} hash The hash to modify.
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
*/
function hashSet(hash, key, value) {
hash[key] = value;
}
/** /**
* Checks if `path` exists on `object`. * Checks if `path` exists on `object`.
* *