vendor/assets/javascripts/lodash.compat.js in lodash-rails-2.4.1 vs vendor/assets/javascripts/lodash.compat.js in lodash-rails-3.1.0

- old
+ new

@@ -1,733 +1,1003 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> - * Build: `lodash -o ./dist/lodash.compat.js` - * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> - * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license <http://lodash.com/license> + * lodash 3.1.0 (Custom Build) <https://lodash.com/> + * Build: `lodash compat -o ./lodash.js` + * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/> + * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE> + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license <https://lodash.com/license> */ ;(function() { - /** Used as a safe reference for `undefined` in pre ES5 environments */ + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; - /** Used to pool arrays and objects used internally */ - var arrayPool = [], - objectPool = []; + /** Used as the semantic version number. */ + var VERSION = '3.1.0'; - /** Used to generate unique IDs */ - var idCounter = 0; + /** Used to compose bitmasks for wrapper metadata. */ + var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, + CURRY_BOUND_FLAG = 4, + CURRY_FLAG = 8, + CURRY_RIGHT_FLAG = 16, + PARTIAL_FLAG = 32, + PARTIAL_RIGHT_FLAG = 64, + REARG_FLAG = 128, + ARY_FLAG = 256; - /** Used internally to indicate various things */ - var indicatorObject = {}; + /** Used as default options for `_.trunc`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; - /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */ - var keyPrefix = +new Date + ''; + /** Used to detect when a function becomes hot. */ + var HOT_COUNT = 150, + HOT_SPAN = 16; - /** Used as the size when optimizations are enabled for large arrays */ - var largeArraySize = 75; + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 0, + LAZY_MAP_FLAG = 1, + LAZY_WHILE_FLAG = 2; - /** Used as the max size of the `arrayPool` and `objectPool` */ - var maxPoolSize = 40; + /** Used as the `TypeError` message for "Functions" methods. */ + var FUNC_ERROR_TEXT = 'Expected a function'; - /** Used to detect and test whitespace */ - var whitespace = ( - // whitespace - ' \t\x0B\f\xA0\ufeff' + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; - // line terminators - '\n\r\u2028\u2029' + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; - // unicode category "Zs" space separators - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); + var arrayBufferTag = '[object ArrayBuffer]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; - /** Used to match empty string literals in compiled template source */ + /** Used to match empty string literals in compiled template source. */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, + reUnescapedHtml = /[&<>"'`]/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + /** - * Used to match ES6 template delimiters - * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals + * Used to match ES template delimiters. + * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) + * for more details. */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; - /** Used to match regexp flags from their coerced string values */ + /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; - /** Used to detected named functions */ + /** Used to detect named functions. */ var reFuncName = /^\s*function[ \n\r\t]+\w/; - /** Used to match "interpolate" template delimiters */ - var reInterpolate = /<%=([\s\S]+?)%>/g; + /** Used to detect hexadecimal string values. */ + var reHexPrefix = /^0[xX]/; - /** Used to match leading whitespace and zeros to be removed */ - var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)'); + /** Used to detect host constructors (Safari > 5). */ + var reHostCtor = /^\[object .+?Constructor\]$/; - /** Used to ensure capturing order of template delimiters */ + /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + + /** Used to ensure capturing order of template delimiters. */ var reNoMatch = /($^)/; - /** Used to detect functions containing a `this` reference */ + /** + * Used to match `RegExp` special characters. + * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) + * for more details. + */ + var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, + reHasRegExpChars = RegExp(reRegExpChars.source); + + /** Used to detect functions containing a `this` reference. */ var reThis = /\bthis\b/; - /** Used to match unescaped characters in compiled string literals */ - var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; - /** Used to assign default `context` object properties */ + /** Used to match words to create compound words. */ + var reWords = (function() { + var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]', + lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+'; + + return RegExp(upper + '{2,}(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); + }()); + + /** Used to detect and test for whitespace. */ + var whitespace = ( + // Basic whitespace characters. + ' \t\x0b\f\xa0\ufeff' + + + // Line terminators. + '\n\r\u2028\u2029' + + + // Unicode category "Zs" space separators. + '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + ); + + /** Used to assign default `context` object properties. */ var contextProps = [ - 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', - 'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN', - 'parseInt', 'setTimeout' + 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', + 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', + 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + 'window', 'WinRTError' ]; - /** Used to fix the JScript [[DontEnum]] bug */ - var shadowedProps = [ + /** Used to fix the JScript `[[DontEnum]]` bug. */ + var shadowProps = [ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf' ]; - /** Used to make template sourceURLs easier to identify */ - var templateCounter = 0; + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; - /** `Object#toString` result shortcuts */ - var argsClass = '[object Arguments]', - arrayClass = '[object Array]', - boolClass = '[object Boolean]', - dateClass = '[object Date]', - errorClass = '[object Error]', - funcClass = '[object Function]', - numberClass = '[object Number]', - objectClass = '[object Object]', - regexpClass = '[object RegExp]', - stringClass = '[object String]'; + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dateTag] = typedArrayTags[errorTag] = + typedArrayTags[funcTag] = typedArrayTags[mapTag] = + typedArrayTags[numberTag] = typedArrayTags[objectTag] = + typedArrayTags[regexpTag] = typedArrayTags[setTag] = + typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; - /** Used to identify object classifications that `_.clone` supports */ - var cloneableClasses = {}; - cloneableClasses[funcClass] = false; - cloneableClasses[argsClass] = cloneableClasses[arrayClass] = - cloneableClasses[boolClass] = cloneableClasses[dateClass] = - cloneableClasses[numberClass] = cloneableClasses[objectClass] = - cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = + cloneableTags[dateTag] = cloneableTags[float32Tag] = + cloneableTags[float64Tag] = cloneableTags[int8Tag] = + cloneableTags[int16Tag] = cloneableTags[int32Tag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[stringTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[mapTag] = cloneableTags[setTag] = + cloneableTags[weakMapTag] = false; - /** Used as an internal `_.debounce` options object */ + /** Used as an internal `_.debounce` options object by `_.throttle`. */ var debounceOptions = { 'leading': false, 'maxWait': 0, 'trailing': false }; - /** Used as the property descriptor for `__bindData__` */ - var descriptor = { - 'configurable': false, - 'enumerable': false, - 'value': null, - 'writable': false + /** Used to map latin-1 supplementary letters to basic latin letters. */ + var deburredLetters = { + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss' }; - /** Used as the data object for `iteratorTemplate` */ - var iteratorData = { - 'args': '', - 'array': null, - 'bottom': '', - 'firstArg': '', - 'init': '', - 'keys': null, - 'loop': '', - 'shadowedProps': null, - 'support': null, - 'top': '', - 'useHas': false + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&amp;', + '<': '&lt;', + '>': '&gt;', + '"': '&quot;', + "'": '&#39;', + '`': '&#96;' }; - /** Used to determine if values are of the language type Object */ + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&amp;': '&', + '&lt;': '<', + '&gt;': '>', + '&quot;': '"', + '&#39;': "'", + '&#96;': '`' + }; + + /** Used to determine if values are of the language type `Object`. */ var objectTypes = { - 'boolean': false, 'function': true, - 'object': true, - 'number': false, - 'string': false, - 'undefined': false + 'object': true }; - /** Used to escape characters for inclusion in compiled string literals */ + /** Used to escape characters for inclusion in compiled string literals. */ var stringEscapes = { '\\': '\\', "'": "'", '\n': 'n', '\r': 'r', - '\t': 't', '\u2028': 'u2028', '\u2029': 'u2029' }; - /** Used as a reference to the global object */ - var root = (objectTypes[typeof window] && window) || this; + /** + * Used as a reference to the global object. + * + * The `this` value is used if it is the global object to avoid Greasemonkey's + * restricted `window` object, otherwise the `window` object is used. + */ + var root = (objectTypes[typeof window] && window !== (this && this.window)) ? window : this; - /** Detect free variable `exports` */ + /** Detect free variable `exports`. */ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; - /** Detect free variable `module` */ + /** Detect free variable `module`. */ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; - /** Detect the popular CommonJS extension `module.exports` */ - var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; - - /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */ - var freeGlobal = objectTypes[typeof global] && global; - if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) { + /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ + var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; + if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { root = freeGlobal; } + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + /*--------------------------------------------------------------------------*/ /** - * The base implementation of `_.indexOf` without support for binary searches - * or `fromIndex` constraints. + * The base implementation of `compareAscending` which compares values and + * sorts them in ascending order without guaranteeing a stable sort. * * @private + * @param {*} value The value to compare to `other`. + * @param {*} other The value to compare to `value`. + * @returns {number} Returns the sort order indicator for `value`. + */ + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsReflexive = value === value, + othIsReflexive = other === other; + + if (value > other || !valIsReflexive || (typeof value == 'undefined' && othIsReflexive)) { + return 1; + } + if (value < other || !othIsReflexive || (typeof other == 'undefined' && valIsReflexive)) { + return -1; + } + } + return 0; + } + + /** + * The base implementation of `_.indexOf` without support for binary searches. + * + * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. + * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } var index = (fromIndex || 0) - 1, - length = array ? array.length : 0; + length = array.length; while (++index < length) { if (array[index] === value) { return index; } } return -1; } /** - * An implementation of `_.contains` for cache objects that mimics the return - * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. + * The base implementation of `_.sortBy` and `_.sortByAll` which uses `comparer` + * to define the sort order of `array` and replaces criteria objects with their + * corresponding values. * * @private - * @param {Object} cache The cache object to inspect. - * @param {*} value The value to search for. - * @returns {number} Returns `0` if `value` is found, else `-1`. + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. */ - function cacheIndexOf(cache, value) { - var type = typeof value; - cache = cache.cache; + function baseSortBy(array, comparer) { + var length = array.length; - if (type == 'boolean' || value == null) { - return cache[value] ? 0 : -1; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; } - if (type != 'number' && type != 'string') { - type = 'object'; + return array; + } + + /** + * Converts `value` to a string if it is not one. An empty string is returned + * for `null` or `undefined` values. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + if (typeof value == 'string') { + return value; } - var key = type == 'number' ? value : keyPrefix + value; - cache = (cache = cache[type]) && cache[key]; + return value == null ? '' : (value + ''); + } - return type == 'object' - ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1) - : (cache ? 0 : -1); + /** + * Used by `_.max` and `_.min` as the default callback for string values. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the code unit of the first character of the string. + */ + function charAtCallback(string) { + return string.charCodeAt(0); } /** - * Adds a given value to the corresponding cache object. + * Used by `_.trim` and `_.trimLeft` to get the index of the first character + * of `string` that is not found in `chars`. * * @private - * @param {*} value The value to add to the cache. + * @param {string} string The string to inspect. + * @param {string} chars The characters to find. + * @returns {number} Returns the index of the first character not found in `chars`. */ - function cachePush(value) { - var cache = this.cache, - type = typeof value; + function charsLeftIndex(string, chars) { + var index = -1, + length = string.length; - if (type == 'boolean' || value == null) { - cache[value] = true; - } else { - if (type != 'number' && type != 'string') { - type = 'object'; - } - var key = type == 'number' ? value : keyPrefix + value, - typeCache = cache[type] || (cache[type] = {}); + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } - if (type == 'object') { - (typeCache[key] || (typeCache[key] = [])).push(value); - } else { - typeCache[key] = true; - } - } + /** + * Used by `_.trim` and `_.trimRight` to get the index of the last character + * of `string` that is not found in `chars`. + * + * @private + * @param {string} string The string to inspect. + * @param {string} chars The characters to find. + * @returns {number} Returns the index of the last character not found in `chars`. + */ + function charsRightIndex(string, chars) { + var index = string.length; + + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; } /** - * Used by `_.max` and `_.min` as the default callback when a given - * collection is a string value. + * Used by `_.sortBy` to compare transformed elements of a collection and stable + * sort them in ascending order. * * @private - * @param {string} value The character to inspect. - * @returns {number} Returns the code unit of given character. + * @param {Object} object The object to compare to `other`. + * @param {Object} other The object to compare to `object`. + * @returns {number} Returns the sort order indicator for `object`. */ - function charAtCallback(value) { - return value.charCodeAt(0); + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index); } /** - * Used by `sortBy` to compare transformed `collection` elements, stable sorting - * them in ascending order. + * Used by `_.sortByAll` to compare multiple properties of each element + * in a collection and stable sort them in ascending order. * * @private - * @param {Object} a The object to compare to `b`. - * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator of `1` or `-1`. + * @param {Object} object The object to compare to `other`. + * @param {Object} other The object to compare to `object`. + * @returns {number} Returns the sort order indicator for `object`. */ - function compareAscending(a, b) { - var ac = a.criteria, - bc = b.criteria, - index = -1, - length = ac.length; + function compareMultipleAscending(object, other) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length; while (++index < length) { - var value = ac[index], - other = bc[index]; - - if (value !== other) { - if (value > other || typeof value == 'undefined') { - return 1; - } - if (value < other || typeof other == 'undefined') { - return -1; - } + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to return the same value for - // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. // // This also ensures a stable sort in V8 and other engines. - // See http://code.google.com/p/v8/issues/detail?id=90 - return a.index - b.index; + // See https://code.google.com/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; } /** - * Creates a cache object to optimize linear searches of large arrays. + * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. * * @private - * @param {Array} [array=[]] The array to search. - * @returns {null|Object} Returns the cache object or `null` if caching should not be used. + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. */ - function createCache(array) { - var index = -1, - length = array.length, - first = array[0], - mid = array[(length / 2) | 0], - last = array[length - 1]; + function deburrLetter(letter) { + return deburredLetters[letter]; + } - if (first && typeof first == 'object' && - mid && typeof mid == 'object' && last && typeof last == 'object') { - return false; - } - var cache = getObject(); - cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false; - - var result = getObject(); - result.array = array; - result.cache = cache; - result.push = cachePush; - - while (++index < length) { - result.push(array[index]); - } - return result; + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; } /** - * Used by `template` to escape characters for inclusion in compiled + * Used by `_.template` to escape characters for inclusion in compiled * string literals. * * @private - * @param {string} match The matched character to escape. + * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ - function escapeStringChar(match) { - return '\\' + stringEscapes[match]; + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; } /** - * Gets an array from the array pool or creates a new one if the pool is empty. + * Gets the index at which the first occurrence of `NaN` is found in `array`. + * If `fromRight` is provided elements of `array` are iterated from right to left. * * @private - * @returns {Array} The array from the pool. + * @param {Array} array The array to search. + * @param {number} [fromIndex] The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched `NaN`, else `-1`. */ - function getArray() { - return arrayPool.pop() || []; + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, + index = fromRight ? (fromIndex || length) : ((fromIndex || 0) - 1); + + while ((fromRight ? index-- : ++index < length)) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; } /** - * Gets an object from the object pool or creates a new one if the pool is empty. + * Checks if `value` is a host object in IE < 9. * * @private - * @returns {Object} The object from the pool. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ - function getObject() { - return objectPool.pop() || { - 'array': null, - 'cache': null, - 'criteria': null, - 'false': false, - 'index': 0, - 'null': false, - 'number': null, - 'object': null, - 'push': null, - 'string': null, - 'true': false, - 'undefined': false, - 'value': null + var isHostObject = (function() { + try { + Object({ 'toString': 0 } + ''); + } catch(e) { + return function() { return false; }; + } + return function(value) { + // IE < 9 presents many host objects as `Object` objects that can coerce + // to strings despite having improperly defined `toString` methods. + return typeof value.toString != 'function' && typeof (value + '') == 'string'; }; - } + }()); /** - * Checks if `value` is a DOM node in IE < 9. + * Checks if `value` is object-like. * * @private * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. */ - function isNode(value) { - // IE < 9 presents DOM nodes as `Object` objects except they have `toString` - // methods that are `typeof` "string" and still can coerce nodes to strings - return typeof value.toString != 'function' && typeof (value + '') == 'string'; + function isObjectLike(value) { + return (value && typeof value == 'object') || false; } /** - * Releases the given array back to the array pool. + * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a + * character code is whitespace. * * @private - * @param {Array} [array] The array to release. + * @param {number} charCode The character code to inspect. + * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`. */ - function releaseArray(array) { - array.length = 0; - if (arrayPool.length < maxPoolSize) { - arrayPool.push(array); - } + function isSpace(charCode) { + return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 || + (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279))); } /** - * Releases the given object back to the object pool. + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. * * @private - * @param {Object} [object] The object to release. + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. */ - function releaseObject(object) { - var cache = object.cache; - if (cache) { - releaseObject(cache); + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = -1, + result = []; + + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } } - object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null; - if (objectPool.length < maxPoolSize) { - objectPool.push(object); - } + return result; } /** - * Slices the `collection` from the `start` index up to, but not including, - * the `end` index. + * An implementation of `_.uniq` optimized for sorted arrays without support + * for callback shorthands and `this` binding. * - * Note: This function is used instead of `Array#slice` to support node lists - * in IE < 9 and to ensure dense arrays are returned. - * * @private - * @param {Array|Object|string} collection The collection to slice. - * @param {number} start The start index. - * @param {number} end The end index. - * @returns {Array} Returns the new array. + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The function invoked per iteration. + * @returns {Array} Returns the new duplicate-value-free array. */ - function slice(array, start, end) { - start || (start = 0); - if (typeof end == 'undefined') { - end = array ? array.length : 0; - } - var index = -1, - length = end - start || 0, - result = Array(length < 0 ? 0 : length); + function sortedUniq(array, iteratee) { + var seen, + index = -1, + length = array.length, + resIndex = -1, + result = []; while (++index < length) { - result[index] = array[start + index]; + var value = array[index], + computed = iteratee ? iteratee(value, index, array) : value; + + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } } return result; } + /** + * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the first non-whitespace character. + */ + function trimmedLeftIndex(string) { + var index = -1, + length = string.length; + + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedRightIndex(string) { + var index = string.length; + + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + /*--------------------------------------------------------------------------*/ /** - * Create a new `lodash` function using the given context object. + * Create a new pristine `lodash` function using the given `context` object. * * @static * @memberOf _ - * @category Utilities + * @category Utility * @param {Object} [context=root] The context object. - * @returns {Function} Returns the `lodash` function. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'add': function(a, b) { return a + b; } }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'sub': function(a, b) { return a - b; } }); + * + * _.isFunction(_.add); + * // => true + * _.isFunction(_.sub); + * // => false + * + * lodash.isFunction(lodash.add); + * // => false + * lodash.isFunction(lodash.sub); + * // => true + * + * // using `context` to mock `Date#getTime` use in `_.now` + * var mock = _.runInContext({ + * 'Date': function() { + * return { 'getTime': getTimeMock }; + * } + * }); + * + * // or creating a suped-up `defer` in Node.js + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; */ function runInContext(context) { // Avoid issues with some ES3 environments that attempt to use values, named // after built-in constructors like `Object`, for the creation of literals. // ES5 clears this up by stating that literals must use built-in constructors. - // See http://es5.github.io/#x11.1.5. + // See https://es5.github.io/#x11.1.5 for more details. context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; - /** Native constructor references */ + /** Native constructor references. */ var Array = context.Array, - Boolean = context.Boolean, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Used for native method references */ - var errorProto = Error.prototype, + /** Used for native method references. */ + var arrayProto = Array.prototype, + errorProto = Error.prototype, objectProto = Object.prototype, stringProto = String.prototype; - /** Used to restore the original `_` reference in `noConflict` */ - var oldDash = context._; + /** Used to detect DOM support. */ + var document = (document = context.window) && document.document; - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; + /** Used to resolve the decompiled source of functions. */ + var fnToString = Function.prototype.toString; - /** Used to detect if a method is native */ + /** Used to the length of n-tuples for `_.unzip`. */ + var getLength = baseProperty('length'); + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** + * Used to resolve the `toStringTag` of values. + * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * for more details. + */ + var objToString = objectProto.toString; + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = context._; + + /** Used to detect if a method is native. */ var reNative = RegExp('^' + - String(toString) - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - .replace(/toString| for [^\]]+/g, '.*?') + '$' + escapeRegExp(objToString) + .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); - /** Native method shortcuts */ - var ceil = Math.ceil, + /** Native method references. */ + var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, + bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, + ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, - fnToString = Function.prototype.toString, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, - hasOwnProperty = objectProto.hasOwnProperty, - push = arrayRef.push, + push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, + Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, - splice = arrayRef.splice, - unshift = arrayRef.unshift; + splice = arrayProto.splice, + Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, + unshift = arrayProto.unshift, + WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; - /** Used to set meta data on functions */ - var defineProperty = (function() { - // IE 8 only accepts DOM elements + /** Used to clone array buffers. */ + var Float64Array = (function() { + // Safari 5 errors when using an array buffer to initialize a typed array + // where the array buffer's `byteLength` is not a multiple of the typed + // array's `BYTES_PER_ELEMENT`. try { - var o = {}, - func = isNative(func = Object.defineProperty) && func, - result = func(o, o, o) && func; - } catch(e) { } + var func = isNative(func = context.Float64Array) && func, + result = new func(new ArrayBuffer(10), 0, 1) && func; + } catch(e) {} return result; }()); - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, - nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, + /* Native method references for those with the same name as other `lodash` methods. */ + var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, + nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsFinite = context.isFinite, - nativeIsNaN = context.isNaN, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, nativeMax = Math.max, nativeMin = Math.min, + nativeNow = isNative(nativeNow = Date.now) && nativeNow, + nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite, nativeParseInt = context.parseInt, nativeRandom = Math.random; - /** Used to lookup a built-in constructor by [[Class]] */ - var ctorByClass = {}; - ctorByClass[arrayClass] = Array; - ctorByClass[boolClass] = Boolean; - ctorByClass[dateClass] = Date; - ctorByClass[funcClass] = Function; - ctorByClass[objectClass] = Object; - ctorByClass[numberClass] = Number; - ctorByClass[regexpClass] = RegExp; - ctorByClass[stringClass] = String; + /** Used as references for `-Infinity` and `Infinity`. */ + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, + POSITIVE_INFINITY = Number.POSITIVE_INFINITY; - /** Used to avoid iterating non-enumerable properties in IE < 9 */ + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used as the size, in bytes, of each `Float64Array` element. */ + var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; + + /** + * Used as the maximum length of an array-like value. + * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * for more details. + */ + var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup a type array constructors by `toStringTag`. */ + var ctorByTag = {}; + ctorByTag[float32Tag] = context.Float32Array; + ctorByTag[float64Tag] = context.Float64Array; + ctorByTag[int8Tag] = context.Int8Array; + ctorByTag[int16Tag] = context.Int16Array; + ctorByTag[int32Tag] = context.Int32Array; + ctorByTag[uint8Tag] = context.Uint8Array; + ctorByTag[uint8ClampedTag] = context.Uint8ClampedArray; + ctorByTag[uint16Tag] = context.Uint16Array; + ctorByTag[uint32Tag] = context.Uint32Array; + + /** Used to avoid iterating over non-enumerable properties in IE < 9. */ var nonEnumProps = {}; - nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; - nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true }; - nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true }; - nonEnumProps[objectClass] = { 'constructor': true }; + nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; + nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true }; + nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true }; + nonEnumProps[objectTag] = { 'constructor': true }; - (function() { - var length = shadowedProps.length; - while (length--) { - var key = shadowedProps[length]; - for (var className in nonEnumProps) { - if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) { - nonEnumProps[className][key] = false; - } + arrayEach(shadowProps, function(key) { + for (var tag in nonEnumProps) { + if (hasOwnProperty.call(nonEnumProps, tag)) { + var props = nonEnumProps[tag]; + props[key] = hasOwnProperty.call(props, key); } } - }()); + }); - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** - * Creates a `lodash` object which wraps the given value to enable intuitive - * method chaining. + * Creates a `lodash` object which wraps `value` to enable intuitive chaining. + * Methods that operate on and return arrays, collections, and functions can + * be chained together. Methods that return a boolean or single value will + * automatically end the chain returning the unwrapped value. Explicit chaining + * may be enabled using `_.chain`. The execution of chained methods is lazy, + * that is, execution is deferred until `_#value` is implicitly or explicitly + * called. * - * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: + * Lazy evaluation allows several methods to support shortcut fusion. Shortcut + * fusion is an optimization that merges iteratees to avoid creating intermediate + * arrays and reduce the number of iteratee executions. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers also have the following `Array` methods: * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, * and `unshift` * - * Chaining is supported in custom builds as long as the `value` method is - * implicitly or explicitly included in the build. + * The wrapper functions that support shortcut fusion are: + * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `first`, + * `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, `slice`, + * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `where` * * The chainable wrapper functions are: - * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, - * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`, - * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`, - * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, - * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, - * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`, - * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`, - * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, - * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, - * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, - * and `zip` + * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, + * `callback`, `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, + * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, + * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, + * `flattenDeep`, `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, + * `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, + * `initial`, `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, + * `mapValues`, `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, + * `omit`, `once`, `pairs`, `partial`, `partialRight`, `partition`, `pick`, + * `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, + * `rearg`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, + * `sortBy`, `sortByAll`, `splice`, `take`, `takeRight`, `takeRightWhile`, + * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, + * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` * - * The non-chainable wrapper functions are: - * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`, - * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`, - * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, - * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, - * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, - * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`, - * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`, - * `template`, `unescape`, `uniqueId`, and `value` + * The wrapper functions that are **not** chainable by default are: + * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, + * `identity`, `includes`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, + * `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, + * `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, + * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, + * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `max`, `min`, + * `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, + * `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, + * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, + * `startCase`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `unescape`, `uniqueId`, `value`, and `words` * - * The wrapper functions `first` and `last` return wrapped values when `n` is - * provided, otherwise they return unwrapped values. + * The wrapper function `sample` will return a wrapped value when `n` is provided, + * otherwise an unwrapped value is returned. * - * Explicit chaining can be enabled by using the `_.chain` method. - * * @name _ * @constructor - * @category Chaining + * @category Chain * @param {*} value The value to wrap in a `lodash` instance. * @returns {Object} Returns a `lodash` instance. * @example * * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value - * wrapped.reduce(function(sum, num) { - * return sum + num; - * }); + * wrapped.reduce(function(sum, n) { return sum + n; }); * // => 6 * * // returns a wrapped value - * var squares = wrapped.map(function(num) { - * return num * num; - * }); + * var squares = wrapped.map(function(n) { return n * n; }); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash(value) { - // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor - return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__')) - ? value - : new lodashWrapper(value); + if (isObjectLike(value) && !isArray(value)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return new LodashWrapper(value.__wrapped__, value.__chain__, arrayCopy(value.__actions__)); + } + } + return new LodashWrapper(value); } /** - * A fast path for creating `lodash` wrapper objects. + * The base constructor for creating `lodash` wrapper objects. * * @private - * @param {*} value The value to wrap in a `lodash` instance. - * @param {boolean} chainAll A flag to enable chaining for all methods - * @returns {Object} Returns a `lodash` instance. + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable chaining for all wrapper methods. + * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value. */ - function lodashWrapper(value, chainAll) { + function LodashWrapper(value, chainAll, actions) { + this.__actions__ = actions || []; this.__chain__ = !!chainAll; this.__wrapped__ = value; } - // ensure `new lodashWrapper` is an instance of `lodash` - lodashWrapper.prototype = lodash.prototype; /** - * An object used to flag environments features. + * An object environment feature flags. * * @static * @memberOf _ * @type Object */ var support = lodash.support = {}; - (function() { - var ctor = function() { this.x = 1; }, + (function(x) { + var Ctor = function() { this.x = 1; }, object = { '0': 1, 'length': 1 }, props = []; - ctor.prototype = { 'valueOf': 1, 'y': 1 }; - for (var key in new ctor) { props.push(key); } - for (key in arguments) { } + Ctor.prototype = { 'valueOf': 1, 'y': 1 }; + for (var key in new Ctor) { props.push(key); } /** - * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9). + * Detect if the `toStringTag` of `arguments` objects is resolvable + * (all but Firefox < 4, IE < 9). * * @memberOf _.support * @type boolean */ - support.argsClass = toString.call(arguments) == argsClass; + support.argsTag = objToString.call(arguments) == argsTag; /** - * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5). - * - * @memberOf _.support - * @type boolean - */ - support.argsObject = arguments.constructor == Object && !(arguments instanceof Array); - - /** * Detect if `name` or `message` properties of `Error.prototype` are - * enumerable by default. (IE < 9, Safari < 5.1) + * enumerable by default (IE < 9, Safari < 5.1). * * @memberOf _.support * @type boolean */ - support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name'); + support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || + propertyIsEnumerable.call(errorProto, 'name'); /** * Detect if `prototype` properties are enumerable by default. * * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 * (if the prototype or a property on the prototype has been set) - * incorrectly sets a function's `prototype` property [[Enumerable]] - * value to `true`. + * incorrectly set the `[[Enumerable]]` value of a function's `prototype` + * property to `true`. * * @memberOf _.support * @type boolean */ - support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype'); + support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype'); /** * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). + * (all but Firefox OS certified apps, older Opera mobile browsers, and + * the PlayStation 3; forced `false` for Windows 8 apps). * * @memberOf _.support * @type boolean */ support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext); @@ -739,81 +1009,107 @@ * @type boolean */ support.funcNames = typeof Function.name == 'string'; /** - * Detect if `arguments` object indexes are non-enumerable - * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1). + * Detect if the `toStringTag` of DOM nodes is resolvable (all but IE < 9). * * @memberOf _.support * @type boolean */ - support.nonEnumArgs = key != 0; + support.nodeTag = objToString.call(document) != objectTag; /** - * Detect if properties shadowing those on `Object.prototype` are non-enumerable. + * Detect if string indexes are non-enumerable + * (IE < 9, RingoJS, Rhino, Narwhal). * - * In IE < 9 an objects own properties, shadowing non-enumerable ones, are - * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug). + * @memberOf _.support + * @type boolean + */ + support.nonEnumStrings = !propertyIsEnumerable.call('x', 0); + + /** + * Detect if properties shadowing those on `Object.prototype` are + * non-enumerable. * + * In IE < 9 an object's own properties, shadowing non-enumerable ones, + * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). + * * @memberOf _.support * @type boolean */ support.nonEnumShadows = !/valueOf/.test(props); /** - * Detect if own properties are iterated after inherited properties (all but IE < 9). + * Detect if own properties are iterated after inherited properties (IE < 9). * * @memberOf _.support * @type boolean */ support.ownLast = props[0] != 'x'; /** - * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly. + * Detect if `Array#shift` and `Array#splice` augment array-like objects + * correctly. * - * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` + * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array `shift()` * and `splice()` functions that fail to remove the last element, `value[0]`, * of array-like objects even though the `length` property is set to `0`. - * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` - * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. + * The `shift()` method is buggy in compatibility modes of IE 8, while `splice()` + * is buggy regardless of mode in IE < 9. * * @memberOf _.support * @type boolean */ - support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]); + support.spliceObjects = (splice.call(object, 0, 1), !object[0]); /** * Detect lack of support for accessing string characters by index. * - * IE < 8 can't access characters by index and IE 8 can only access - * characters by index on string literals. + * IE < 8 can't access characters by index. IE 8 can only access characters + * by index on string literals, not string objects. * * @memberOf _.support * @type boolean */ support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx'; /** - * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9) - * and that the JS engine errors when attempting to coerce an object to - * a string without a `toString` function. + * Detect if the DOM is supported. * * @memberOf _.support * @type boolean */ try { - support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + '')); + support.dom = document.createDocumentFragment().nodeType === 11; } catch(e) { - support.nodeClass = true; + support.dom = false; } - }(1)); + /** + * Detect if `arguments` object indexes are non-enumerable. + * + * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object + * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat + * `arguments` object indexes as non-enumerable and fail `hasOwnProperty` + * checks for indexes that exceed their function's formal parameters with + * associated values of `0`. + * + * @memberOf _.support + * @type boolean + */ + try { + support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1); + } catch(e) { + support.nonEnumArgs = true; + } + }(0, 0)); + /** - * By default, the template delimiters used by Lo-Dash are similar to those in - * embedded Ruby (ERB). Change the following template settings to use alternative - * delimiters. + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB). Change the following template settings to use + * alternative delimiters. * * @static * @memberOf _ * @type Object */ @@ -823,19 +1119,19 @@ * Used to detect `data` property values to be HTML-escaped. * * @memberOf _.templateSettings * @type RegExp */ - 'escape': /<%-([\s\S]+?)%>/g, + 'escape': reEscape, /** * Used to detect code to be evaluated. * * @memberOf _.templateSettings * @type RegExp */ - 'evaluate': /<%([\s\S]+?)%>/g, + 'evaluate': reEvaluate, /** * Used to detect `data` property values to inject. * * @memberOf _.templateSettings @@ -867,3374 +1163,5260 @@ */ '_': lodash } }; - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** - * The template used to create iterator functions. + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. * * @private - * @param {Object} data The data object used to populate the text. - * @returns {string} Returns the interpolated text. + * @param {*} value The value to wrap. */ - var iteratorTemplate = function(obj) { + function LazyWrapper(value) { + this.actions = null; + this.dir = 1; + this.dropCount = 0; + this.filtered = false; + this.iteratees = null; + this.takeCount = POSITIVE_INFINITY; + this.views = null; + this.wrapped = value; + } - var __p = 'var index, iterable = ' + - (obj.firstArg) + - ', result = ' + - (obj.init) + - ';\nif (!iterable) return result;\n' + - (obj.top) + - ';'; - if (obj.array) { - __p += '\nvar length = iterable.length; index = -1;\nif (' + - (obj.array) + - ') { '; - if (support.unindexedChars) { - __p += '\n if (isString(iterable)) {\n iterable = iterable.split(\'\')\n } '; - } - __p += '\n while (++index < length) {\n ' + - (obj.loop) + - ';\n }\n}\nelse { '; - } else if (support.nonEnumArgs) { - __p += '\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += \'\';\n ' + - (obj.loop) + - ';\n }\n } else { '; - } + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var actions = this.actions, + iteratees = this.iteratees, + views = this.views, + result = new LazyWrapper(this.wrapped); - if (support.enumPrototypes) { - __p += '\n var skipProto = typeof iterable == \'function\';\n '; - } + result.actions = actions ? arrayCopy(actions) : null; + result.dir = this.dir; + result.dropCount = this.dropCount; + result.filtered = this.filtered; + result.iteratees = iteratees ? arrayCopy(iteratees) : null; + result.takeCount = this.takeCount; + result.views = views ? arrayCopy(views) : null; + return result; + } - if (support.enumErrorProps) { - __p += '\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n '; - } + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.filtered) { + var result = new LazyWrapper(this); + result.dir = -1; + result.filtered = true; + } else { + result = this.clone(); + result.dir *= -1; + } + return result; + } - var conditions = []; if (support.enumPrototypes) { conditions.push('!(skipProto && index == "prototype")'); } if (support.enumErrorProps) { conditions.push('!(skipErrorProps && (index == "message" || index == "name"))'); } + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.wrapped.value(); + if (!isArray(array)) { + return baseWrapperValue(array, this.actions); + } + var dir = this.dir, + isRight = dir < 0, + view = getView(0, array.length, this.views), + start = view.start, + end = view.end, + length = end - start, + dropCount = this.dropCount, + takeCount = nativeMin(length, this.takeCount - dropCount), + index = isRight ? end : start - 1, + iteratees = this.iteratees, + iterLength = iteratees ? iteratees.length : 0, + resIndex = 0, + result = []; - if (obj.useHas && obj.keys) { - __p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n'; - if (conditions.length) { - __p += ' if (' + - (conditions.join(' && ')) + - ') {\n '; - } - __p += - (obj.loop) + - '; '; - if (conditions.length) { - __p += '\n }'; - } - __p += '\n } '; - } else { - __p += '\n for (index in iterable) {\n'; - if (obj.useHas) { conditions.push("hasOwnProperty.call(iterable, index)"); } if (conditions.length) { - __p += ' if (' + - (conditions.join(' && ')) + - ') {\n '; - } - __p += - (obj.loop) + - '; '; - if (conditions.length) { - __p += '\n }'; - } - __p += '\n } '; - if (support.nonEnumShadows) { - __p += '\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n '; - for (k = 0; k < 7; k++) { - __p += '\n index = \'' + - (obj.shadowedProps[k]) + - '\';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))'; - if (!obj.useHas) { - __p += ' || (!nonEnum[index] && iterable[index] !== objectProto[index])'; - } - __p += ') {\n ' + - (obj.loop) + - ';\n } '; - } - __p += '\n } '; - } + outer: + while (length-- && resIndex < takeCount) { + index += dir; - } + var iterIndex = -1, + value = array[index]; - if (obj.array || support.nonEnumArgs) { - __p += '\n}'; - } - __p += - (obj.bottom) + - ';\nreturn result'; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + computed = iteratee(value, index, array), + type = data.type; - return __p - }; + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + if (dropCount) { + dropCount--; + } else { + result[resIndex++] = value; + } + } + return result; + } - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** - * The base implementation of `_.bind` that creates the bound function and - * sets its meta data. + * Creates a cache object to store key/value pairs. * * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new bound function. + * @static + * @name Cache + * @memberOf _.memoize */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; + function MapCache() { + this.__data__ = {}; + } - function bound() { - // `Function#bind` spec - // http://es5.github.io/#x15.3.4.5 - if (partialArgs) { - // avoid `arguments` object deoptimizations by using `slice` instead - // of `Array.prototype.slice.call` and not assigning `arguments` to a - // variable as a ternary expression - var args = slice(partialArgs); - push.apply(args, arguments); - } - // mimic the constructor's `return` behavior - // http://es5.github.io/#x13.2.2 - if (this instanceof bound) { - // ensure `new bound` is an instance of `func` - var thisBinding = baseCreate(func.prototype), - result = func.apply(thisBinding, args || arguments); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisArg, args || arguments); + /** + * Removes `key` and its value from the cache. + * + * @private + * @name delete + * @memberOf _.memoize.Cache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`. + */ + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + + /** + * Gets the cached value for `key`. + * + * @private + * @name get + * @memberOf _.memoize.Cache + * @param {string} key The key of the value to get. + * @returns {*} Returns the cached value. + */ + function mapGet(key) { + return key == '__proto__' ? undefined : this.__data__[key]; + } + + /** + * Checks if a cached value for `key` exists. + * + * @private + * @name has + * @memberOf _.memoize.Cache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapHas(key) { + return key != '__proto__' && hasOwnProperty.call(this.__data__, key); + } + + /** + * Adds `value` to `key` of the cache. + * + * @private + * @name set + * @memberOf _.memoize.Cache + * @param {string} key The key of the value to cache. + * @param {*} value The value to cache. + * @returns {Object} Returns the cache object. + */ + function mapSet(key, value) { + if (key != '__proto__') { + this.__data__[key] = value; } - setBindData(bound, bindData); - return bound; + return this; } + /*------------------------------------------------------------------------*/ + /** - * The base implementation of `_.clone` without argument juggling or support - * for `thisArg` binding. * + * Creates a cache object to store unique values. + * * @private - * @param {*} value The value to clone. - * @param {boolean} [isDeep=false] Specify a deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates clones with source counterparts. - * @returns {*} Returns the cloned value. + * @param {Array} [values] The values to cache. */ - function baseClone(value, isDeep, callback, stackA, stackB) { - if (callback) { - var result = callback(value); - if (typeof result != 'undefined') { - return result; - } + function SetCache(values) { + var length = values ? values.length : 0; + + this.data = { 'hash': nativeCreate(null), 'set': new Set }; + while (length--) { + this.push(values[length]); } - // inspect [[Class]] - var isObj = isObject(value); - if (isObj) { - var className = toString.call(value); - if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) { - return value; - } - var ctor = ctorByClass[className]; - switch (className) { - case boolClass: - case dateClass: - return new ctor(+value); + } - case numberClass: - case stringClass: - return new ctor(value); + /** + * Checks if `value` is in `cache` mimicking the return signature of + * `_.indexOf` by returning `0` if the value is found, else `-1`. + * + * @private + * @param {Object} cache The cache to search. + * @param {*} value The value to search for. + * @returns {number} Returns `0` if `value` is found, else `-1`. + */ + function cacheIndexOf(cache, value) { + var data = cache.data, + result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value]; - case regexpClass: - result = ctor(value.source, reFlags.exec(value)); - result.lastIndex = value.lastIndex; - return result; - } + return result ? 0 : -1; + } + + /** + * Adds `value` to the cache. + * + * @private + * @name push + * @memberOf SetCache + * @param {*} value The value to cache. + */ + function cachePush(value) { + var data = this.data; + if (typeof value == 'string' || isObject(value)) { + data.set.add(value); } else { - return value; + data.hash[value] = true; } - var isArr = isArray(value); - if (isDeep) { - // check for circular references and return corresponding clone - var initedStack = !stackA; - stackA || (stackA = getArray()); - stackB || (stackB = getArray()); + } - var length = stackA.length; - while (length--) { - if (stackA[length] == value) { - return stackB[length]; - } + /*------------------------------------------------------------------------*/ + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function arrayCopy(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * A specialized version of `_.forEach` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; } - result = isArr ? ctor(value.length) : {}; } - else { - result = isArr ? slice(value) : assign({}, value); + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * callback shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } } - // add array properties assigned by `RegExp#exec` - if (isArr) { - if (hasOwnProperty.call(value, 'index')) { - result.index = value.index; + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; } - if (hasOwnProperty.call(value, 'input')) { - result.input = value.input; + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array.length, + resIndex = -1, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; } } - // exit for shallow clone - if (!isDeep) { - return result; + return result; + } + + /** + * A specialized version of `_.map` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); } - // add the source value to the stack of traversed objects - // and associate it with its clone - stackA.push(value); - stackB.push(result); + return result; + } - // recursively populate clone (susceptible to call stack limits) - (isArr ? baseEach : forOwn)(value, function(objValue, key) { - result[key] = baseClone(objValue, isDeep, callback, stackA, stackB); - }); + /** + * A specialized version of `_.max` for arrays without support for iteratees. + * + * @private + * @param {Array} array The array to iterate over. + * @returns {*} Returns the maximum value. + */ + function arrayMax(array) { + var index = -1, + length = array.length, + result = NEGATIVE_INFINITY; - if (initedStack) { - releaseArray(stackA); - releaseArray(stackB); + while (++index < length) { + var value = array[index]; + if (value > result) { + result = value; + } } return result; } /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. + * A specialized version of `_.min` for arrays without support for iteratees. * * @private - * @param {Object} prototype The object to inherit from. - * @returns {Object} Returns the new object. + * @param {Array} array The array to iterate over. + * @returns {*} Returns the minimum value. */ - function baseCreate(prototype, properties) { - return isObject(prototype) ? nativeCreate(prototype) : {}; + function arrayMin(array) { + var index = -1, + length = array.length, + result = POSITIVE_INFINITY; + + while (++index < length) { + var value = array[index]; + if (value < result) { + result = value; + } + } + return result; } - // fallback for browsers without `Object.create` - if (!nativeCreate) { - baseCreate = (function() { - function Object() {} - return function(prototype) { - if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; - } - return result || context.Object(); - }; - }()); + + /** + * A specialized version of `_.reduce` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initFromArray] Specify using the first element of `array` + * as the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, + length = array.length; + + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; } /** - * The base implementation of `_.createCallback` without support for creating - * "_.pluck" or "_.where" style callbacks. + * A specialized version of `_.reduceRight` for arrays without support for + * callback shorthands or `this` binding. * * @private - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initFromArray] Specify using the last element of `array` + * as the initial value. + * @returns {*} Returns the accumulated value. */ - function baseCreateCallback(func, thisArg, argCount) { - if (typeof func != 'function') { - return identity; + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { - return func; + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { - if (support.funcNames) { - bindData = !func.name; + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; } - bindData = bindData || !support.funcDecomp; - if (!bindData) { - var source = fnToString.call(func); - if (!support.funcNames) { - bindData = !reFuncName.test(source); - } - if (!bindData) { - // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); - } + } + return false; + } + + /** + * Used by `_.defaults` to customize its `_.assign` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. + */ + function assignDefaults(objectValue, sourceValue) { + return typeof objectValue == 'undefined' ? sourceValue : objectValue; + } + + /** + * Used by `_.template` to customize its `_.assign` use. + * + * **Note:** This method is like `assignDefaults` except that it ignores + * inherited property values when checking if a property is `undefined`. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @param {string} key The key associated with the object and source values. + * @param {Object} object The destination object. + * @returns {*} Returns the value to assign to the destination object. + */ + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return (typeof objectValue == 'undefined' || !hasOwnProperty.call(object, key)) + ? sourceValue + : objectValue; + } + + /** + * The base implementation of `_.assign` without support for argument juggling, + * multiple sources, and `this` binding `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {Function} [customizer] The function to customize assigning values. + * @returns {Object} Returns the destination object. + */ + function baseAssign(object, source, customizer) { + var props = keys(source); + if (!customizer) { + return baseCopy(source, object, props); + } + var index = -1, + length = props.length + + while (++index < length) { + var key = props[index], + value = object[key], + result = customizer(value, source[key], key, object, source); + + if ((result === result ? result !== value : value === value) || + (typeof value == 'undefined' && !(key in object))) { + object[key] = result; } } - // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & 1)) { - return func; + return object; + } + + /** + * The base implementation of `_.at` without support for strings and individual + * key arguments. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {number[]|string[]} [props] The property names or indexes of elements to pick. + * @returns {Array} Returns the new array of picked elements. + */ + function baseAt(collection, props) { + var index = -1, + length = collection.length, + isArr = isLength(length), + propsLength = props.length, + result = Array(propsLength); + + while(++index < propsLength) { + var key = props[index]; + if (isArr) { + key = parseFloat(key); + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = collection[key]; + } } - switch (argCount) { - case 1: return function(value) { - return func.call(thisArg, value); - }; - case 2: return function(a, b) { - return func.call(thisArg, a, b); - }; - case 3: return function(value, index, collection) { - return func.call(thisArg, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(thisArg, accumulator, value, index, collection); - }; + return result; + } + + /** + * Copies the properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Object} [object={}] The object to copy properties to. + * @param {Array} props The property names to copy. + * @returns {Object} Returns `object`. + */ + function baseCopy(source, object, props) { + if (!props) { + props = object; + object = {}; } - return bind(func, thisArg); + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; } /** - * The base implementation of `createWrapper` that creates the wrapper and - * sets its meta data. + * The base implementation of `_.bindAll` without support for individual + * method name arguments. * * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new function. + * @param {Object} object The object to bind and assign the bound methods to. + * @param {string[]} methodNames The object method names to bind. + * @returns {Object} Returns `object`. */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; + function baseBindAll(object, methodNames) { + var index = -1, + length = methodNames.length; - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - key = func; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + } - function bound() { - var thisBinding = isBind ? thisArg : this; - if (partialArgs) { - var args = slice(partialArgs); - push.apply(args, arguments); + /** + * The base implementation of `_.callback` which supports specifying the + * number of arguments to provide to `func`. + * + * @private + * @param {*} [func=_.identity] The value to convert to a callback. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {number} [argCount] The number of arguments to provide to `func`. + * @returns {Function} Returns the callback. + */ + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == 'function') { + return (typeof thisArg != 'undefined' && isBindable(func)) + ? bindCallback(func, thisArg, argCount) + : func; + } + if (func == null) { + return identity; + } + // Handle "_.property" and "_.matches" style callback shorthands. + return type == 'object' + ? baseMatches(func) + : baseProperty(func + ''); + } + + /** + * The base implementation of `_.clone` without support for argument juggling + * and `this` binding `customizer` functions. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The object `value` belongs to. + * @param {Array} [stackA=[]] Tracks traversed source objects. + * @param {Array} [stackB=[]] Associates clones with source counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (typeof result != 'undefined') { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); } - if (partialRightArgs || isCurry) { - args || (args = slice(arguments)); - if (partialRightArgs) { - push.apply(args, partialRightArgs); + } else { + var tag = objToString.call(value), + isFunc = tag == funcTag; + + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + if (isHostObject(value)) { + return object ? value : {}; } - if (isCurry && args.length < arity) { - bitmask |= 16 & ~32; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]); + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseCopy(value, result, keys(value)); } + } else { + return cloneableTags[tag] + ? initCloneByTag(value, tag, isDeep) + : (object ? value : {}); } - args || (args = arguments); - if (isBindKey) { - func = thisBinding[key]; + } + // Check for circular references and return corresponding clone. + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; } - if (this instanceof bound) { - thisBinding = baseCreate(func.prototype); - var result = func.apply(thisBinding, args); - return isObject(result) ? result : thisBinding; + } + // Add the source value to the stack of traversed objects and associate it with its clone. + stackA.push(value); + stackB.push(result); + + // Recursively populate clone (susceptible to call stack limits). + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} prototype The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function Object() {} + return function(prototype) { + if (isObject(prototype)) { + Object.prototype = prototype; + var result = new Object; + Object.prototype = null; } - return func.apply(thisBinding, args); + return result || context.Object(); + }; + }()); + + /** + * The base implementation of `_.delay` and `_.defer` which accepts an index + * of where to slice the arguments to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Object} args The `arguments` object to slice and provide to `func`. + * @returns {number} Returns the timer id. + */ + function baseDelay(func, wait, args, fromIndex) { + if (!isFunction(func)) { + throw new TypeError(FUNC_ERROR_TEXT); } - setBindData(bound, bindData); - return bound; + return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait); } /** - * The base implementation of `_.difference` that accepts a single array + * The base implementation of `_.difference` which accepts a single array * of values to exclude. * * @private - * @param {Array} array The array to process. - * @param {Array} [values] The array of values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @returns {Array} Returns the new array of filtered values. */ function baseDifference(array, values) { + var length = array ? array.length : 0, + result = []; + + if (!length) { + return result; + } var index = -1, indexOf = getIndexOf(), - length = array ? array.length : 0, - isLarge = length >= largeArraySize && indexOf === baseIndexOf, - result = []; + isCommon = indexOf == baseIndexOf, + cache = isCommon && values.length >= 200 && createCache(values), + valuesLength = values.length; - if (isLarge) { - var cache = createCache(values); - if (cache) { - indexOf = cacheIndexOf; - values = cache; - } else { - isLarge = false; - } + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; } + outer: while (++index < length) { var value = array[index]; - if (indexOf(values, value) < 0) { + + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } result.push(value); } + else if (indexOf(values, value) < 0) { + result.push(value); + } } - if (isLarge) { - releaseObject(values); + return result; + } + + /** + * The base implementation of `_.forEach` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object|string} Returns `collection`. + */ + function baseEach(collection, iteratee) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + return baseForOwn(collection, iteratee); } + var index = -1, + iterable = toObject(collection); + + while (++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + } + + /** + * The base implementation of `_.forEachRight` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object|string} Returns `collection`. + */ + function baseEachRight(collection, iteratee) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + return baseForOwnRight(collection, iteratee); + } + var iterable = toObject(collection); + while (length--) { + if (iteratee(iterable[length], length, iterable) === false) { + break; + } + } + return collection; + } + + /** + * The base implementation of `_.every` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); return result; } /** - * The base implementation of `_.flatten` without support for callback - * shorthands or `thisArg` binding. + * The base implementation of `_.filter` without support for callback + * shorthands or `this` binding. * * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`, + * without support for callback shorthands and `this` binding, which iterates + * over `collection` using the provided `eachFunc`. + * + * @private + * @param {Array|Object|string} collection The collection to search. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @param {boolean} [retKey] Specify returning the key of the found element + * instead of the element itself. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with added support for restricting + * flattening and specifying the start index. + * + * @private * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects. + * @param {boolean} [isDeep] Specify a deep flatten. + * @param {boolean} [isStrict] Restrict flattening to arrays and `arguments` objects. * @param {number} [fromIndex=0] The index to start from. - * @returns {Array} Returns a new flattened array. + * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, isShallow, isStrict, fromIndex) { + function baseFlatten(array, isDeep, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, - length = array ? array.length : 0, + length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index]; - if (value && typeof value == 'object' && typeof value.length == 'number' - && (isArray(value) || isArguments(value))) { - // recursively flatten arrays (susceptible to call stack limits) - if (!isShallow) { - value = baseFlatten(value, isShallow, isStrict); + if (isObjectLike(value) && isLength(value.length) && (isArray(value) || isArguments(value))) { + if (isDeep) { + // Recursively flatten arrays (susceptible to call stack limits). + value = baseFlatten(value, isDeep, isStrict); } var valIndex = -1, - valLength = value.length, - resIndex = result.length; + valLength = value.length; result.length += valLength; while (++valIndex < valLength) { - result[resIndex++] = value[valIndex]; + result[++resIndex] = value[valIndex]; } } else if (!isStrict) { - result.push(value); + result[++resIndex] = value; } } return result; } /** - * The base implementation of `_.isEqual`, without support for `thisArg` binding, - * that allows partial "_.where" style comparisons. + * The base implementation of `baseForIn` and `baseForOwn` which iterates + * over `object` properties returned by `keysFunc` invoking `iteratee` for + * each property. Iterator functions may exit iteration early by explicitly + * returning `false`. * * @private - * @param {*} a The value to compare. - * @param {*} b The other value to compare. - * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. - * @param {Array} [stackA=[]] Tracks traversed `a` objects. - * @param {Array} [stackB=[]] Tracks traversed `b` objects. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. */ - function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { - // used to indicate that when comparing objects, `a` has at least the properties of `b` - if (callback) { - var result = callback(a, b); - if (typeof result != 'undefined') { - return !!result; + function baseFor(object, iteratee, keysFunc) { + var index = -1, + iterable = toObject(object), + props = keysFunc(object), + length = props.length; + + while (++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; } } - // exit early for identical values - if (a === b) { - // treat `+0` vs. `-0` as not equal - return a !== 0 || (1 / a == 1 / b); + return object; + } + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + function baseForRight(object, iteratee, keysFunc) { + var iterable = toObject(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[length]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } } - var type = typeof a, - otherType = typeof b; + return object; + } - // exit early for unlike primitive values - if (a === a && - !(a && objectTypes[type]) && - !(b && objectTypes[otherType])) { - return false; + /** + * The base implementation of `_.forIn` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + + /** + * The base implementation of `_.forOwn` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from those provided. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the new array of filtered property names. + */ + function baseFunctions(object, props) { + var index = -1, + length = props.length, + resIndex = -1, + result = []; + + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } } - // exit early for `null` and `undefined` avoiding ES3's Function#call behavior - // http://es5.github.io/#x15.3.4.4 - if (a == null || b == null) { - return a === b; + return result; + } + + /** + * The base implementation of `_.invoke` which requires additional arguments + * to be provided as an array of arguments rather than individually. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|string} methodName The name of the method to invoke or + * the function invoked per iteration. + * @param {Array} [args] The arguments to invoke the method with. + * @returns {Array} Returns the array of results. + */ + function baseInvoke(collection, methodName, args) { + var index = -1, + isFunc = typeof methodName == 'function', + length = collection ? collection.length : 0, + result = isLength(length) ? Array(length) : []; + + baseEach(collection, function(value) { + var func = isFunc ? methodName : (value != null && value[methodName]); + result[++index] = func ? func.apply(value, args) : undefined; + }); + return result; + } + + /** + * The base implementation of `_.isEqual` without support for `this` binding + * `customizer` functions. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparing values. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, customizer, isWhere, stackA, stackB) { + // Exit early for identical values. + if (value === other) { + // Treat `+0` vs. `-0` as not equal. + return value !== 0 || (1 / value == 1 / other); } - // compare [[Class]] names - var className = toString.call(a), - otherClass = toString.call(b); + var valType = typeof value, + othType = typeof other; - if (className == argsClass) { - className = objectClass; + // Exit early for unlike primitive values. + if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') || + value == null || other == null) { + // Return `false` unless both values are `NaN`. + return value !== value && other !== other; } - if (otherClass == argsClass) { - otherClass = objectClass; + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isWhere, stackA, stackB); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing objects. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA=[]] Tracks traversed `value` objects. + * @param {Array} [stackB=[]] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, stackB) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = arrayTag, + othTag = arrayTag; + + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } } - if (className != otherClass) { - return false; + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } } - switch (className) { - case boolClass: - case dateClass: - // coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +a == +b; + var objIsObj = objTag == objectTag && !isHostObject(object), + othIsObj = othTag == objectTag && !isHostObject(other), + isSameTag = objTag == othTag; - case numberClass: - // treat `NaN` vs. `NaN` as equal - return (a != +a) - ? b != +b - // but treat `+0` vs. `-0` as not equal - : (a == 0 ? (1 / a == 1 / b) : a == +b); + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); - case regexpClass: - case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) - // treat string primitives and their corresponding object instances as equal - return a == String(b); + if (valWrapped || othWrapped) { + return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB); } - var isArr = className == arrayClass; - if (!isArr) { - // unwrap any `lodash` wrapped values - var aWrapped = hasOwnProperty.call(a, '__wrapped__'), - bWrapped = hasOwnProperty.call(b, '__wrapped__'); + if (!isSameTag) { + return false; + } + // Assume cyclic values are equal. + // For more information on detecting circular references see https://es5.github.io/#JO. + stackA || (stackA = []); + stackB || (stackB = []); - if (aWrapped || bWrapped) { - return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; } - // exit for functions and DOM nodes - if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) { - return false; - } - // in older versions of Opera, `arguments` objects have `Array` constructors - var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor, - ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor; + } + // Add `object` and `other` to the stack of traversed objects. + stackA.push(object); + stackB.push(other); - // non `Object` object instances with different constructors are not equal - if (ctorA != ctorB && - !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && - ('constructor' in a && 'constructor' in b) + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isWhere, stackA, stackB); + + stackA.pop(); + stackB.pop(); + + return result; + } + + /** + * The base implementation of `_.isMatch` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Object} source The object to inspect. + * @param {Array} props The source property names to match. + * @param {Array} values The source values to match. + * @param {Array} strictCompareFlags Strict comparison flags for source values. + * @param {Function} [customizer] The function to customize comparing objects. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, props, values, strictCompareFlags, customizer) { + var length = props.length; + if (object == null) { + return !length; + } + var index = -1, + noCustomizer = !customizer; + + while (++index < length) { + if ((noCustomizer && strictCompareFlags[index]) + ? values[index] !== object[props[index]] + : !hasOwnProperty.call(object, props[index]) ) { return false; } } - // assume cyclic structures are equal - // the algorithm for detecting cyclic structures is adapted from ES 5.1 - // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) - var initedStack = !stackA; - stackA || (stackA = getArray()); - stackB || (stackB = getArray()); + index = -1; + while (++index < length) { + var key = props[index]; + if (noCustomizer && strictCompareFlags[index]) { + var result = hasOwnProperty.call(object, key); + } else { + var objValue = object[key], + srcValue = values[index]; - var length = stackA.length; - while (length--) { - if (stackA[length] == a) { - return stackB[length] == b; + result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (typeof result == 'undefined') { + result = baseIsEqual(srcValue, objValue, customizer, true); + } } + if (!result) { + return false; + } } - var size = 0; - result = true; + return true; + } - // add `a` and `b` to the stack of traversed objects - stackA.push(a); - stackB.push(b); + /** + * The base implementation of `_.map` without support for callback shorthands + * or `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var result = []; + baseEach(collection, function(value, key, collection) { + result.push(iteratee(value, key, collection)); + }); + return result; + } - // recursively compare objects and arrays (susceptible to call stack limits) - if (isArr) { - // compare lengths to determine if a deep comparison is necessary - length = a.length; - size = b.length; - result = size == length; + /** + * The base implementation of `_.matches` which supports specifying whether + * `source` should be cloned. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new function. + */ + function baseMatches(source) { + var props = keys(source), + length = props.length; - if (result || isWhere) { - // deep compare the contents, ignoring non-numeric properties - while (size--) { - var index = length, - value = b[size]; + if (length == 1) { + var key = props[0], + value = source[key]; - if (isWhere) { - while (index--) { - if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { - break; - } - } - } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { - break; - } - } + if (isStrictComparable(value)) { + return function(object) { + return object != null && value === object[key] && hasOwnProperty.call(object, key); + }; } } - else { - // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` - // which, in this case, is more costly - forIn(b, function(value, key, b) { - if (hasOwnProperty.call(b, key)) { - // count the number of properties. - size++; - // deep compare each property value. - return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); - } - }); + var values = Array(length), + strictCompareFlags = Array(length); - if (result && !isWhere) { - // ensure both objects have the same number of properties - forIn(a, function(value, key, a) { - if (hasOwnProperty.call(a, key)) { - // `size` will be `-1` if `a` has more properties than `b` - return (result = --size > -1); - } - }); - } + while (length--) { + value = source[props[length]]; + values[length] = value; + strictCompareFlags[length] = isStrictComparable(value); } - stackA.pop(); - stackB.pop(); + return function(object) { + return baseIsMatch(object, props, values, strictCompareFlags); + }; + } - if (initedStack) { - releaseArray(stackA); - releaseArray(stackB); - } - return result; + /** + * The base implementation of `_.merge` without support for argument juggling, + * multiple sources, and `this` binding `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {Function} [customizer] The function to customize merging properties. + * @param {Array} [stackA=[]] Tracks traversed source objects. + * @param {Array} [stackB=[]] Associates values with source counterparts. + * @returns {Object} Returns the destination object. + */ + function baseMerge(object, source, customizer, stackA, stackB) { + var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source)); + + (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + return baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } + var value = object[key], + result = customizer ? customizer(value, srcValue, key, object, source) : undefined, + isCommon = typeof result == 'undefined'; + + if (isCommon) { + result = srcValue; + } + if ((isSrcArr || typeof result != 'undefined') && + (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + }); + return object; } /** - * The base implementation of `_.merge` without argument juggling or support - * for `thisArg` binding. + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. - * @param {Function} [callback] The function to customize merging properties. + * @param {string} key The key of the value to merge. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize merging properties. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ - function baseMerge(object, source, callback, stackA, stackB) { - (isArray(source) ? forEach : forOwn)(source, function(source, key) { - var found, - isArr, - result = source, - value = object[key]; + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, + srcValue = source[key]; - if (source && ((isArr = isArray(source)) || isPlainObject(source))) { - // avoid merging previously merged cyclic sources - var stackLength = stackA.length; - while (stackLength--) { - if ((found = stackA[stackLength] == source)) { - value = stackB[stackLength]; - break; - } - } - if (!found) { - var isShallow; - if (callback) { - result = callback(value, source); - if ((isShallow = typeof result != 'undefined')) { - value = result; - } - } - if (!isShallow) { - value = isArr - ? (isArray(value) ? value : []) - : (isPlainObject(value) ? value : {}); - } - // add `source` and associated `value` to the stack of traversed objects - stackA.push(source); - stackB.push(value); + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], + result = customizer ? customizer(value, srcValue, key, object, source) : undefined, + isCommon = typeof result == 'undefined'; - // recursively merge objects and arrays (susceptible to call stack limits) - if (!isShallow) { - baseMerge(value, source, callback, stackA, stackB); - } - } + if (isCommon) { + result = srcValue; + if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) + ? value + : (value ? arrayCopy(value) : []); } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) + ? toPlainObject(value) + : (isPlainObject(value) ? value : {}); + } else { - if (callback) { - result = callback(value, source); - if (typeof result == 'undefined') { - result = source; - } - } - if (typeof result != 'undefined') { - value = result; - } + isCommon = false; } - object[key] = value; - }); + } + // Add the source value to the stack of traversed objects and associate + // it with its merged value. + stackA.push(srcValue); + stackB.push(result); + + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } } /** - * The base implementation of `_.random` without argument juggling or support - * for returning floating-point numbers. + * The base implementation of `_.property` which does not coerce `key` to a string. * * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * index arguments. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + */ + function basePullAt(array, indexes) { + var length = indexes.length, + result = baseAt(array, indexes); + + indexes.sort(baseCompareAscending); + while (length--) { + var index = parseFloat(indexes[length]); + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return result; + } + + /** + * The base implementation of `_.random` without support for argument juggling + * and returning floating-point numbers. + * + * @private * @param {number} min The minimum possible value. * @param {number} max The maximum possible value. - * @returns {number} Returns a random number. + * @returns {number} Returns the random number. */ function baseRandom(min, max) { return min + floor(nativeRandom() * (max - min + 1)); } /** + * The base implementation of `_.reduce` and `_.reduceRight` without support + * for callback shorthands or `this` binding, which iterates over `collection` + * using the provided `eachFunc`. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initFromCollection Specify using the first or last element + * of `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection + ? (initFromCollection = false, value) + : iteratee(accumulator, value, index, collection) + }); + return accumulator; + } + + /** + * The base implementation of `setData` without support for hot loop detection. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + start = start == null ? 0 : (+start || 0); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (typeof end == 'undefined' || end > length) ? length : (+end || 0); + if (end < 0) { + end += length; + } + length = start > end ? 0 : (end - start) >>> 0; + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for callback shorthands + * or `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** * The base implementation of `_.uniq` without support for callback shorthands - * or `thisArg` binding. + * and `this` binding. * * @private - * @param {Array} array The array to process. - * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. - * @param {Function} [callback] The function called per iteration. - * @returns {Array} Returns a duplicate-value-free array. + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The function invoked per iteration. + * @returns {Array} Returns the new duplicate-value-free array. */ - function baseUniq(array, isSorted, callback) { + function baseUniq(array, iteratee) { var index = -1, indexOf = getIndexOf(), - length = array ? array.length : 0, + length = array.length, + isCommon = indexOf == baseIndexOf, + isLarge = isCommon && length >= 200, + seen = isLarge && createCache(), result = []; - var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf, - seen = (callback || isLarge) ? getArray() : result; - - if (isLarge) { - var cache = createCache(seen); + if (seen) { indexOf = cacheIndexOf; - seen = cache; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; } + outer: while (++index < length) { var value = array[index], - computed = callback ? callback(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; - if (isSorted - ? !index || seen[seen.length - 1] !== computed - : indexOf(seen, computed) < 0 - ) { - if (callback || isLarge) { + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { seen.push(computed); } result.push(value); } + else if (indexOf(seen, computed) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } } - if (isLarge) { - releaseArray(seen.array); - releaseObject(seen); - } else if (callback) { - releaseArray(seen); + return result; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * returned by `keysFunc`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + var index = -1, + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; } return result; } /** - * Creates a function that aggregates a collection, creating an object composed - * of keys generated from the results of running each element of the collection - * through a callback. The given `setter` function sets the keys and values - * of the composed object. + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. * * @private - * @param {Function} setter The setter function. + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to peform to resolve the unwrapped value. + * @returns {*} Returns the resolved unwrapped value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, + length = actions.length; + + while (++index < length) { + var args = [result], + action = actions[index]; + + push.apply(args, action.args); + result = action.func.apply(action.thisArg, args); + } + return result; + } + + /** + * Performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest, instead + * of the lowest, index at which a value should be inserted into `array`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function binaryIndex(array, value, retHighest) { + var low = 0, + high = array ? array.length : low; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (retHighest ? (computed <= value) : (computed < value)) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + + /** + * This function is like `binaryIndex` except that it invokes `iteratee` for + * `value` and each element of `array` to compute their sort ranking. The + * iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The function invoked per iteration. + * @param {boolean} [retHighest] Specify returning the highest, instead + * of the lowest, index at which a value should be inserted into `array`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + + var low = 0, + high = array ? array.length : 0, + valIsNaN = value !== value, + valIsUndef = typeof value == 'undefined'; + + while (low < high) { + var mid = floor((low + high) / 2), + computed = iteratee(array[mid]), + isReflexive = computed === computed; + + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || typeof computed != 'undefined'); + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * A specialized version of `baseCallback` which only supports `this` binding + * and specifying the number of arguments to provide to `func`. + * + * @private + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {number} [argCount] The number of arguments to provide to `func`. + * @returns {Function} Returns the callback. + */ + function bindCallback(func, thisArg, argCount) { + if (typeof func != 'function') { + return identity; + } + if (typeof thisArg == 'undefined') { + return func; + } + switch (argCount) { + case 1: return function(value) { + return func.call(thisArg, value); + }; + case 3: return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + case 5: return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function bufferClone(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`. + bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, + offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, + result = new ArrayBuffer(byteLength); + + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } + return result; + }; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array|Object} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, + argsIndex = -1, + argsLength = nativeMax(args.length - holdersLength, 0), + leftIndex = -1, + leftLength = partials.length, + result = Array(argsLength + leftLength); + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array|Object} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, + holdersLength = holders.length, + argsIndex = -1, + argsLength = nativeMax(args.length - holdersLength, 0), + rightIndex = -1, + rightLength = partials.length, + result = Array(argsLength + rightLength); + + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var pad = argsIndex; + while (++rightIndex < rightLength) { + result[pad + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[pad + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + + /** + * Creates a function that aggregates a collection, creating an accumulator + * object composed from the results of running each element in the collection + * through an iteratee. The `setter` sets the keys and values of the accumulator + * object. If `initializer` is provided initializes the accumulator object. + * + * @private + * @param {Function} setter The function to set keys and values of the accumulator object. + * @param {Function} [initializer] The function to initialize the accumulator object. * @returns {Function} Returns the new aggregator function. */ - function createAggregator(setter) { - return function(collection, callback, thisArg) { - var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; - setter(result, value, callback(value, index, collection), collection); + setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { - setter(result, value, callback(value, key, collection), collection); + setter(result, value, iteratee(value, key, collection), collection); }); } return result; }; } /** - * Creates a function that, when called, either curries or invokes `func` - * with an optional `this` binding and partially applied arguments. + * Creates a function that assigns properties of source object(s) to a given + * destination object. * * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return function() { + var length = arguments.length, + object = arguments[0]; + + if (length < 2 || object == null) { + return object; + } + if (length > 3 && isIterateeCall(arguments[1], arguments[2], arguments[3])) { + length = 2; + } + // Juggle arguments. + if (length > 3 && typeof arguments[length - 2] == 'function') { + var customizer = bindCallback(arguments[--length - 1], arguments[length--], 5); + } else if (length > 2 && typeof arguments[length - 1] == 'function') { + customizer = arguments[--length]; + } + var index = 0; + while (++index < length) { + var source = arguments[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` and invokes it with the `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new bound function. + */ + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + + function wrapper() { + return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); + } + return wrapper; + } + + /** + * Creates a `Set` cache object to optimize linear searches of large arrays. + * + * @private + * @param {Array} [values] The values to cache. + * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. + */ + var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { + return new SetCache(values); + }; + + /** + * Creates a function that produces compound words out of the words in a + * given string. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + var index = -1, + array = words(deburr(string)), + length = array.length, + result = ''; + + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtorWrapper(Ctor) { + return function() { + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, arguments); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that gets the extremum value of a collection. + * + * @private + * @param {Function} arrayFunc The function to get the extremum value from an array. + * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum, + * extremum value. + * @returns {Function} Returns the new extremum function. + */ + function createExtremum(arrayFunc, isMin) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = null; + } + var func = getCallback(), + noIteratee = iteratee == null; + + if (!(func === baseCallback && noIteratee)) { + noIteratee = false; + iteratee = func(iteratee, thisArg, 3); + } + if (noIteratee) { + var isArr = isArray(collection); + if (!isArr && isString(collection)) { + iteratee = charAtCallback; + } else { + return arrayFunc(isArr ? collection : toIterable(collection)); + } + } + return extremumBy(collection, iteratee, isMin); + }; + } + + /** + * Creates a function that wraps `func` and invokes it with optional `this` + * binding of, partial application, and currying. + * + * @private * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of method flags to compose. - * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) - * 16 - `_.partial` - * 32 - `_.partialRight` - * @param {Array} [partialArgs] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [partialRightArgs] An array of arguments to append to those - * provided to the new function. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new wrapped function. */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - isPartial = bitmask & 16, - isPartialRight = bitmask & 32; + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, + isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurry = bitmask & CURRY_FLAG, + isCurryBound = bitmask & CURRY_BOUND_FLAG, + isCurryRight = bitmask & CURRY_RIGHT_FLAG; + var Ctor = !isBindKey && createCtorWrapper(func), + key = func; + + function wrapper() { + // Avoid `arguments` object use disqualifying optimizations by + // converting it to an array before providing it to other functions. + var length = arguments.length, + index = length, + args = Array(length); + + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, + argsHolders = replaceHolders(args, placeholder); + + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : null, + newArity = nativeMax(arity - length, 0), + newsHolders = isCurry ? argsHolders : null, + newHoldersRight = isCurry ? null : argsHolders, + newPartials = isCurry ? args : null, + newPartialsRight = isCurry ? null : args; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var result = createHybridWrapper(func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity); + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this; + if (isBindKey) { + func = thisBinding[key]; + } + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates the pad required for `string` based on the given padding length. + * The `chars` string may be truncated if the number of padding characters + * exceeds the padding length. + * + * @private + * @param {string} string The string to create padding for. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the pad for `string`. + */ + function createPad(string, length, chars) { + var strLength = string.length; + length = +length; + + if (strLength >= length || !nativeIsFinite(length)) { + return ''; + } + var padLength = length - strLength; + chars = chars == null ? ' ' : (chars + ''); + return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + } + + /** + * Creates a function that wraps `func` and invokes it with the optional `this` + * binding of `thisArg` and the `partials` prepended to those provided to + * the wrapper. + * + * @private + * @param {Function} func The function to partially apply arguments to. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to the new function. + * @returns {Function} Returns the new bound function. + */ + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtorWrapper(func); + + function wrapper() { + // Avoid `arguments` object use disqualifying optimizations by + // converting it to an array before providing it `func`. + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(argsLength + leftLength); + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. + * The bitmask may be composed of the following flags: + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && !isFunction(func)) { - throw new TypeError; + throw new TypeError(FUNC_ERROR_TEXT); } - if (isPartial && !partialArgs.length) { - bitmask &= ~16; - isPartial = partialArgs = false; + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = null; } - if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; - isPartialRight = partialRightArgs = false; + length -= (holders ? holders.length : 0); + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = null; } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); + var data = !isBindKey && getData(func), + newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; + + if (data && data !== true) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null + ? (isBindKey ? 0 : func.length) + : (nativeMax(arity - length, 0) || 0); + + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(null, newData); + } else { + result = createHybridWrapper.apply(null, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing arrays. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, equalFunc, customizer, isWhere, stackA, stackB) { + var index = -1, + arrLength = array.length, + othLength = other.length, + result = true; + + if (arrLength != othLength && !(isWhere && othLength > arrLength)) { + return false; + } + // Deep compare the contents, ignoring non-numeric properties. + while (result && ++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + result = undefined; + if (customizer) { + result = isWhere + ? customizer(othValue, arrValue, index) + : customizer(arrValue, othValue, index); } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); + if (typeof result == 'undefined') { + // Recursively compare arrays (susceptible to call stack limits). + if (isWhere) { + var othIndex = othLength; + while (othIndex--) { + othValue = other[othIndex]; + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + if (result) { + break; + } + } + } else { + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + } } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & 1)) { - bindData[4] = thisArg; + } + return !!result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} value The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + // Coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0` treating invalid dates coerced to `NaN` as not equal. + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + // Treat `NaN` vs. `NaN` as equal. + return (object != +object) + ? other != +other + // But, treat `-0` vs. `+0` as not equal. + : (object == 0 ? ((1 / object) == (1 / other)) : object == +other); + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings primitives and string + // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. + return object == (other + ''); + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing values. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, equalFunc, customizer, isWhere, stackA, stackB) { + var objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isWhere) { + return false; + } + var hasCtor, + index = -1; + + while (++index < objLength) { + var key = objProps[index], + result = hasOwnProperty.call(other, key); + + if (result) { + var objValue = object[key], + othValue = other[key]; + + result = undefined; + if (customizer) { + result = isWhere + ? customizer(othValue, objValue, key) + : customizer(objValue, othValue, key); + } + if (typeof result == 'undefined') { + // Recursively compare objects (susceptible to call stack limits). + result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isWhere, stackA, stackB); + } } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & 1) { - bitmask |= 8; + if (!result) { + return false; } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & 4)) { - bindData[5] = arity; + hasCtor || (hasCtor = key == 'constructor'); + } + if (!hasCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { + return false; } - // append partial left arguments - if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); + } + return true; + } + + /** + * Gets the extremum value of `collection` invoking `iteratee` for each value + * in `collection` to generate the criterion by which the value is ranked. + * The `iteratee` is invoked with three arguments; (value, index, collection). + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {boolean} [isMin] Specify returning the minimum, instead of the + * maximum, extremum value. + * @returns {*} Returns the extremum value. + */ + function extremumBy(collection, iteratee, isMin) { + var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY, + computed = exValue, + result = computed; + + baseEach(collection, function(value, index, collection) { + var current = iteratee(value, index, collection); + if ((isMin ? current < computed : current > computed) || (current === exValue && current === result)) { + computed = current; + result = value; } - // append partial right arguments - if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); + }); + return result; + } + + /** + * Gets the appropriate "callback" function. If the `_.callback` method is + * customized this function returns the custom method, otherwise it returns + * the `baseCallback` function. If arguments are provided the chosen function + * is invoked with them and its result is returned. + * + * @private + * @returns {Function} Returns the chosen function or its result. + */ + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the appropriate "indexOf" function. If the `_.indexOf` method is + * customized this function returns the custom method, otherwise it returns + * the `baseIndexOf` function. If arguments are provided the chosen function + * is invoked with them and its result is returned. + * + * @private + * @returns {Function|number} Returns the chosen function or its result. + */ + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} [transforms] The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms ? transforms.length : 0; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; } - // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); } - // fast path for `_.bind` - var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); + return { 'start': start, 'end': end }; } /** - * Creates compiled iteration functions. + * Initializes an array clone. * * @private - * @param {...Object} [options] The compile options object(s). - * @param {string} [options.array] Code to determine if the iterable is an array or array-like. - * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop. - * @param {Function} [options.keys] A reference to `_.keys` for use in own property iteration. - * @param {string} [options.args] A comma separated string of iteration function arguments. - * @param {string} [options.top] Code to execute before the iteration branches. - * @param {string} [options.loop] Code to execute in the object loop. - * @param {string} [options.bottom] Code to execute after the iteration branches. - * @returns {Function} Returns the compiled function. + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. */ - function createIterator() { - // data properties - iteratorData.shadowedProps = shadowedProps; + function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); - // iterator options - iteratorData.array = iteratorData.bottom = iteratorData.loop = iteratorData.top = ''; - iteratorData.init = 'iterable'; - iteratorData.useHas = true; + // Add array properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } - // merge options into a template data object - for (var object, index = 0; object = arguments[index]; index++) { - for (var key in object) { - iteratorData[key] = object[key]; + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + // Safari 5 mobile incorrectly has `Object` as the constructor of typed arrays. + if (Ctor instanceof Ctor) { + Ctor = ctorByTag[tag]; + } + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + + /** + * Checks if `func` is eligible for `this` binding. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is eligible, else `false`. + */ + function isBindable(func) { + var support = lodash.support, + result = !(support.funcNames ? func.name : support.funcDecomp); + + if (!result) { + var source = fnToString.call(func); + if (!support.funcNames) { + result = !reFuncName.test(source); } + if (!result) { + // Check if `func` references the `this` keyword and store the result. + result = reThis.test(source) || isNative(func); + baseSetData(func, result); + } } - var args = iteratorData.args; - iteratorData.firstArg = /^[^,]+/.exec(args)[0]; + return result; + } - // create the function factory - var factory = Function( - 'baseCreateCallback, errorClass, errorProto, hasOwnProperty, ' + - 'indicatorObject, isArguments, isArray, isString, keys, objectProto, ' + - 'objectTypes, nonEnumProps, stringClass, stringProto, toString', - 'return function(' + args + ') {\n' + iteratorTemplate(iteratorData) + '\n}' - ); + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + value = +value; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } - // return the compiled function - return factory( - baseCreateCallback, errorClass, errorProto, hasOwnProperty, - indicatorObject, isArguments, isArray, isString, iteratorData.keys, objectProto, - objectTypes, nonEnumProps, stringClass, stringProto, toString - ); + /** + * Checks if the provided arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number') { + var length = object.length, + prereq = isLength(length) && isIndex(index, length); + } else { + prereq = type == 'string' && index in object; + } + return prereq && object[index] === value; } /** - * Used by `escape` to convert characters to HTML entities. + * Checks if `value` is a valid array-like length. * + * **Note:** This function is based on ES `ToLength`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) + * for more details. + * * @private - * @param {string} match The matched character to escape. - * @returns {string} Returns the escaped character. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. */ - function escapeHtmlChar(match) { - return htmlEscapes[match]; + function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } /** - * Gets the appropriate "indexOf" function. If the `_.indexOf` method is - * customized, this method returns the custom method, otherwise it returns - * the `baseIndexOf` function. + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * * @private - * @returns {Function} Returns the "indexOf" function. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. */ - function getIndexOf() { - var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result; + function isStrictComparable(value) { + return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value)); + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers required to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg` + * augment function arguments, making the order in which they are executed important, + * preventing the merging of metadata. However, we make an exception for a safe + * common case where curried functions have `_.ary` and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask; + + var arityFlags = ARY_FLAG | REARG_FLAG, + bindFlags = BIND_FLAG | BIND_KEY_FLAG, + comboFlags = arityFlags | bindFlags | CURRY_BOUND_FLAG | CURRY_RIGHT_FLAG; + + var isAry = bitmask & ARY_FLAG && !(srcBitmask & ARY_FLAG), + isRearg = bitmask & REARG_FLAG && !(srcBitmask & REARG_FLAG), + argPos = (isRearg ? data : source)[7], + ary = (isAry ? data : source)[8]; + + var isCommon = !(bitmask >= REARG_FLAG && srcBitmask > bindFlags) && + !(bitmask > bindFlags && srcBitmask >= REARG_FLAG); + + var isCombo = (newBitmask >= arityFlags && newBitmask <= comboFlags) && + (bitmask < REARG_FLAG || ((isRearg || isAry) && argPos.length <= ary)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + // Use source `ary` if it's smaller. + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * A specialized version of `_.pick` that picks `object` properties specified + * by the `props` array. + * + * @private + * @param {Object} object The source object. + * @param {string[]} props The property names to pick. + * @returns {Object} Returns the new object. + */ + function pickByArray(object, props) { + object = toObject(object); + + var index = -1, + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } return result; } /** - * Checks if `value` is a native function. + * A specialized version of `_.pick` that picks `object` properties `predicate` + * returns truthy for. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. + * @param {Object} object The source object. + * @param {Function} predicate The function invoked per iteration. + * @returns {Object} Returns the new object. */ - function isNative(value) { - return typeof value == 'function' && reNative.test(value); + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; } /** - * Sets `this` binding data on a given function. + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. * * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. */ - var setBindData = !defineProperty ? noop : function(func, value) { - descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); - }; + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + /** - * A fallback implementation of `isPlainObject` which checks if a given value - * is an object created by the `Object` constructor, assuming objects created - * by the `Object` constructor have no inherited enumerable properties and that - * there are no `Object.prototype` extensions. + * Sets metadata for `func`. * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity function + * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070) + * for more details. + * * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = (function() { + var count = 0, + lastCalled = 0; + + return function(key, value) { + var stamp = now(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }()); + + /** + * A fallback implementation of `_.isPlainObject` which checks if `value` + * is an object created by the `Object` constructor or has a `[[Prototype]]` + * of `null`. + * + * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { - var ctor, - result; + var Ctor, + support = lodash.support; - // avoid non Object objects, `arguments` objects, and DOM elements - if (!(value && toString.call(value) == objectClass) || - (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor)) || - (!support.argsClass && isArguments(value)) || - (!support.nodeClass && isNode(value))) { + // Exit early for non `Object` objects. + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value)) || + (!hasOwnProperty.call(value, 'constructor') && + (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor))) || + (!support.argsTag && isArguments(value))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first // iterated property is an object's own property then there are no inherited // enumerable properties. + var result; if (support.ownLast) { - forIn(value, function(value, key, object) { + baseForIn(value, function(subValue, key, object) { result = hasOwnProperty.call(object, key); return false; }); return result !== false; } // In most environments an object's own properties are iterated before // its inherited properties. If the last iterated property is an object's // own property then there are no inherited enumerable properties. - forIn(value, function(value, key) { + baseForIn(value, function(subValue, key) { result = key; }); return typeof result == 'undefined' || hasOwnProperty.call(value, result); } /** - * Used by `unescape` to convert HTML entities to characters. + * A fallback implementation of `Object.keys` which creates an array of the + * own enumerable property names of `object`. * * @private - * @param {string} match The matched character to unescape. - * @returns {string} Returns the unescaped character. + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. */ - function unescapeHtmlChar(match) { - return htmlUnescapes[match]; - } + function shimKeys(object) { + var props = keysIn(object), + propsLength = props.length, + length = propsLength && object.length, + support = lodash.support; - /*--------------------------------------------------------------------------*/ + var allowIndexes = length && isLength(length) && + (isArray(object) || (support.nonEnumStrings && isString(object)) || + (support.nonEnumArgs && isArguments(object))); - /** - * Checks if `value` is an `arguments` object. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`. - * @example - * - * (function() { return _.isArguments(arguments); })(1, 2, 3); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */ - function isArguments(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == argsClass || false; + var index = -1, + result = []; + + while (++index < propsLength) { + var key = props[index]; + if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; } - // fallback for browsers that can't detect `arguments` objects by [[Class]] - if (!support.argsClass) { - isArguments = function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false; - }; - } /** - * Checks if `value` is an array. + * Converts `value` to an array-like object if it is not one. * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an array, else `false`. - * @example - * - * (function() { return _.isArray(arguments); })(); - * // => false - * - * _.isArray([1, 2, 3]); - * // => true + * @private + * @param {*} value The value to process. + * @returns {Array|Object} Returns the array-like object. */ - var isArray = nativeIsArray || function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass || false; - }; + function toIterable(value) { + if (value == null) { + return []; + } + if (!isLength(value.length)) { + return values(value); + } + if (lodash.support.unindexedChars && isString(value)) { + return value.split(''); + } + return isObject(value) ? value : Object(value); + } /** - * A fallback implementation of `Object.keys` which produces an array of the - * given object's own enumerable property names. + * Converts `value` to an object if it is not one. * * @private - * @type Function - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. + * @param {*} value The value to process. + * @returns {Object} Returns the object. */ - var shimKeys = createIterator({ - 'args': 'object', - 'init': '[]', - 'top': 'if (!(objectTypes[typeof object])) return result', - 'loop': 'result.push(index)' - }); + function toObject(value) { + if (lodash.support.unindexedChars && isString(value)) { + var index = -1, + length = value.length, + result = Object(value); + while (++index < length) { + result[index] = value.charAt(index); + } + return result; + } + return isObject(value) ? value : Object(value); + } + + /*------------------------------------------------------------------------*/ + /** - * Creates an array composed of the own enumerable property names of an object. + * Creates an array of elements split into groups the length of `size`. + * If `collection` can't be split evenly, the final chunk will be the remaining + * elements. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. + * @category Array + * @param {Array} array The array to process. + * @param {numer} [size=1] The length of each chunk. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the new array containing chunks. * @example * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] */ - var keys = !nativeKeys ? shimKeys : function(object) { - if (!isObject(object)) { - return []; + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(+size || 1, 1); } - if ((support.enumPrototypes && typeof object == 'function') || - (support.nonEnumArgs && object.length && isArguments(object))) { - return shimKeys(object); + var index = 0, + length = array ? array.length : 0, + resIndex = -1, + result = Array(ceil(length / size)); + + while (index < length) { + result[++resIndex] = baseSlice(array, index, (index += size)); } - return nativeKeys(object); - }; + return result; + } - /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */ - var eachIteratorOptions = { - 'args': 'collection, callback, thisArg', - 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)", - 'array': "typeof length == 'number'", - 'keys': keys, - 'loop': 'if (callback(iterable[index], index, collection) === false) return result' - }; - - /** Reusable iterator options for `assign` and `defaults` */ - var defaultsIteratorOptions = { - 'args': 'object, source, guard', - 'top': - 'var args = arguments,\n' + - ' argsIndex = 0,\n' + - " argsLength = typeof guard == 'number' ? 2 : args.length;\n" + - 'while (++argsIndex < argsLength) {\n' + - ' iterable = args[argsIndex];\n' + - ' if (iterable && objectTypes[typeof iterable]) {', - 'keys': keys, - 'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]", - 'bottom': ' }\n}' - }; - - /** Reusable iterator options for `forIn` and `forOwn` */ - var forOwnIteratorOptions = { - 'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top, - 'array': false - }; - /** - * Used to convert characters to HTML entities: + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. * - * Though the `>` character is escaped for symmetry, characters like `>` and `/` - * don't require escaping in HTML and have no special meaning unless they're part - * of a tag or an unquoted attribute value. - * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] */ - var htmlEscapes = { - '&': '&amp;', - '<': '&lt;', - '>': '&gt;', - '"': '&quot;', - "'": '&#39;' - }; + function compact(array) { + var index = -1, + length = array ? array.length : 0, + resIndex = -1, + result = []; - /** Used to convert HTML entities to characters */ - var htmlUnescapes = invert(htmlEscapes); + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } - /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'), - reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g'); - /** - * A function compiled to iterate `arguments` objects, arrays, objects, and - * strings consistenly across environments, executing the callback for each - * element in the collection. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index|key, collection). Callbacks may exit - * iteration early by explicitly returning `false`. + * Creates an array excluding all values of the provided arrays using + * `SameValueZero` for equality comparisons. * - * @private - * @type Function - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array|Object|string} Returns `collection`. + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The arrays of values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.difference([1, 2, 3], [5, 2, 10]); + * // => [1, 3] */ - var baseEach = createIterator(eachIteratorOptions); + function difference() { + var index = -1, + length = arguments.length; - /*--------------------------------------------------------------------------*/ + while (++index < length) { + var value = arguments[index]; + if (isArray(value) || isArguments(value)) { + break; + } + } + return baseDifference(value, baseFlatten(arguments, false, true, ++index)); + } /** - * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with two - * arguments; (objectValue, sourceValue). + * Creates a slice of `array` with `n` elements dropped from the beginning. * * @static * @memberOf _ * @type Function - * @alias extend - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize assigning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. * @example * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } + * _.drop([1, 2, 3]); + * // => [2, 3] * - * var defaults = _.partialRight(_.assign, function(a, b) { - * return typeof a == 'undefined' ? b : a; - * }); + * _.drop([1, 2, 3], 2); + * // => [3] * - * var object = { 'name': 'barney' }; - * defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] */ - var assign = createIterator(defaultsIteratorOptions, { - 'top': - defaultsIteratorOptions.top.replace(';', - ';\n' + - "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" + - ' var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n' + - "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" + - ' callback = args[--argsLength];\n' + - '}' - ), - 'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]' - }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } /** - * Creates a clone of `value`. If `isDeep` is `true` nested objects will also - * be cloned, otherwise they will be assigned by reference. If a callback - * is provided it will be executed to produce the cloned values. If the - * callback returns `undefined` cloning will be handled by the method instead. - * The callback is bound to `thisArg` and invoked with one argument; (value). + * Creates a slice of `array` with `n` elements dropped from the end. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to clone. - * @param {boolean} [isDeep=false] Specify a deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the cloned value. + * @type Function + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * _.dropRight([1, 2, 3]); + * // => [1, 2] * - * var shallow = _.clone(characters); - * shallow[0] === characters[0]; - * // => true + * _.dropRight([1, 2, 3], 2); + * // => [1] * - * var deep = _.clone(characters, true); - * deep[0] === characters[0]; - * // => false + * _.dropRight([1, 2, 3], 5); + * // => [] * - * _.mixin({ - * 'clone': _.partialRight(_.clone, function(value) { - * return _.isElement(value) ? value.cloneNode(false) : undefined; - * }) - * }); - * - * var clone = _.clone(document.body); - * clone.childNodes.length; - * // => 0 + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] */ - function clone(value, isDeep, callback, thisArg) { - // allows working with "Collections" methods without using their `index` - // and `collection` arguments for `isDeep` and `callback` - if (typeof isDeep != 'boolean' && isDeep != null) { - thisArg = callback; - callback = isDeep; - isDeep = false; + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; } - return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); } /** - * Creates a deep clone of `value`. If a callback is provided it will be - * executed to produce the cloned values. If the callback returns `undefined` - * cloning will be handled by the method instead. The callback is bound to - * `thisArg` and invoked with one argument; (value). + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). * - * Note: This method is loosely based on the structured clone algorithm. Functions - * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and - * objects created by constructors other than `Object` are cloned to plain `Object` objects. - * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the deep cloned value. + * @type Function + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per element. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * _.dropRightWhile([1, 2, 3], function(n) { return n > 1; }); + * // => [1] + * + * var users = [ + * { 'user': 'barney', 'status': 'busy', 'active': false }, + * { 'user': 'fred', 'status': 'busy', 'active': true }, + * { 'user': 'pebbles', 'status': 'away', 'active': true } * ]; * - * var deep = _.cloneDeep(characters); - * deep[0] === characters[0]; - * // => false + * // using the "_.property" callback shorthand + * _.pluck(_.dropRightWhile(users, 'active'), 'user'); + * // => ['barney'] * - * var view = { - * 'label': 'docs', - * 'node': element - * }; - * - * var clone = _.cloneDeep(view, function(value) { - * return _.isElement(value) ? value.cloneNode(true) : undefined; - * }); - * - * clone.node == view.node; - * // => false + * // using the "_.matches" callback shorthand + * _.pluck(_.dropRightWhile(users, { 'status': 'away' }), 'user'); + * // => ['barney', 'fred'] */ - function cloneDeep(value, callback, thisArg) { - return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); + function dropRightWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + predicate = getCallback(predicate, thisArg, 3); + while (length-- && predicate(array[length], length, array)) {} + return baseSlice(array, 0, length + 1); } /** - * Creates an object that inherits from the given `prototype` object. If a - * `properties` object is provided its own enumerable properties are assigned - * to the created object. + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Objects - * @param {Object} prototype The object to inherit from. - * @param {Object} [properties] The properties to assign to the object. - * @returns {Object} Returns the new object. + * @type Function + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per element. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * _.dropWhile([1, 2, 3], function(n) { return n < 3; }); + * // => [3] * - * function Circle() { - * Shape.call(this); - * } + * var users = [ + * { 'user': 'barney', 'status': 'busy', 'active': true }, + * { 'user': 'fred', 'status': 'busy', 'active': false }, + * { 'user': 'pebbles', 'status': 'away', 'active': true } + * ]; * - * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); + * // using the "_.property" callback shorthand + * _.pluck(_.dropWhile(users, 'active'), 'user'); + * // => ['fred', 'pebbles'] * - * var circle = new Circle; - * circle instanceof Circle; - * // => true - * - * circle instanceof Shape; - * // => true + * // using the "_.matches" callback shorthand + * _.pluck(_.dropWhile(users, { 'status': 'busy' }), 'user'); + * // => ['pebbles'] */ - function create(prototype, properties) { - var result = baseCreate(prototype); - return properties ? assign(result, properties) : result; + function dropWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var index = -1; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) {} + return baseSlice(array, index); } /** - * Assigns own enumerable properties of source object(s) to the destination - * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional defaults of the same property will be ignored. + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for, instead of the element itself. * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param- {Object} [guard] Allows working with `_.reduce` without using its - * `key` and `object` arguments as sources. - * @returns {Object} Returns the destination object. + * @category Array + * @param {Array} array The array to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {number} Returns the index of the found element, else `-1`. * @example * - * var object = { 'name': 'barney' }; - * _.defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.findIndex(users, function(chr) { return chr.age < 40; }); + * // => 0 + * + * // using the "_.matches" callback shorthand + * _.findIndex(users, { 'age': 1 }); + * // => 2 + * + * // using the "_.property" callback shorthand + * _.findIndex(users, 'active'); + * // => 1 */ - var defaults = createIterator(defaultsIteratorOptions); + function findIndex(array, predicate, thisArg) { + var index = -1, + length = array ? array.length : 0; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + /** - * This method is like `_.findIndex` except that it returns the key of the - * first element that passes the callback check, instead of the element itself. + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @category Array + * @param {Array} array The array to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {number} Returns the index of the found element, else `-1`. * @example * - * var characters = { - * 'barney': { 'age': 36, 'blocked': false }, - * 'fred': { 'age': 40, 'blocked': true }, - * 'pebbles': { 'age': 1, 'blocked': false } - * }; + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; * - * _.findKey(characters, function(chr) { - * return chr.age < 40; - * }); - * // => 'barney' (property order is not guaranteed across environments) + * _.findLastIndex(users, function(chr) { return chr.age < 40; }); + * // => 2 * - * // using "_.where" callback shorthand - * _.findKey(characters, { 'age': 1 }); - * // => 'pebbles' + * // using the "_.matches" callback shorthand + * _.findLastIndex(users, { 'age': 40 }); + * // => 1 * - * // using "_.pluck" callback shorthand - * _.findKey(characters, 'blocked'); - * // => 'fred' + * // using the "_.property" callback shorthand + * _.findLastIndex(users, 'active'); + * // => 0 */ - function findKey(object, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - forOwn(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; + function findLastIndex(array, predicate, thisArg) { + var length = array ? array.length : 0; + predicate = getCallback(predicate, thisArg, 3); + while (length--) { + if (predicate(array[length], length, array)) { + return length; } - }); - return result; + } + return -1; } /** - * This method is like `_.findKey` except that it iterates over elements - * of a `collection` in the opposite order. + * Gets the first element of `array`. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @alias head + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. * @example * - * var characters = { - * 'barney': { 'age': 36, 'blocked': true }, - * 'fred': { 'age': 40, 'blocked': false }, - * 'pebbles': { 'age': 1, 'blocked': true } - * }; + * _.first([1, 2, 3]); + * // => 1 * - * _.findLastKey(characters, function(chr) { - * return chr.age < 40; - * }); - * // => returns `pebbles`, assuming `_.findKey` returns `barney` - * - * // using "_.where" callback shorthand - * _.findLastKey(characters, { 'age': 40 }); - * // => 'fred' - * - * // using "_.pluck" callback shorthand - * _.findLastKey(characters, 'blocked'); - * // => 'pebbles' + * _.first([]); + * // => undefined */ - function findLastKey(object, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - forOwnRight(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; - } - }); - return result; + function first(array) { + return array ? array[0] : undefined; } /** - * Iterates over own and inherited enumerable properties of an object, - * executing the callback for each property. The callback is bound to `thisArg` - * and invoked with three arguments; (value, key, object). Callbacks may exit - * iteration early by explicitly returning `false`. + * Flattens a nested array. If `isDeep` is `true` the array is recursively + * flattened, otherwise it is only flattened a single level. * * @static * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Array + * @param {Array} array The array to flatten. + * @param {boolean} [isDeep] Specify a deep flatten. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the new flattened array. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * _.flatten([1, [2], [3, [[4]]]]); + * // => [1, 2, 3, [[4]]]; * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; + * // using `isDeep` + * _.flatten([1, [2], [3, [[4]]]], true); + * // => [1, 2, 3, 4]; + */ + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + + /** + * Recursively flattens a nested array. * - * _.forIn(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to recursively flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2], [3, [[4]]]]); + * // => [1, 2, 3, 4]; */ - var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, { - 'useHas': false - }); + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } /** - * This method is like `_.forIn` except that it iterates over elements - * of a `collection` in the opposite order. + * Gets the index at which the first occurrence of `value` is found in `array` + * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, + * it is used as the offset from the end of `array`. If `array` is sorted + * providing `true` for `fromIndex` performs a faster binary search. * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {boolean|number} [fromIndex=0] The index to search from or `true` + * to perform a binary search on a sorted array. + * @returns {number} Returns the index of the matched value, else `-1`. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * _.indexOf([1, 2, 3, 1, 2, 3], 2); + * // => 1 * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; + * // using `fromIndex` + * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 4 * - * _.forInRight(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move' + * // performing a binary search + * _.indexOf([4, 4, 5, 5, 6, 6], 5, true); + * // => 2 */ - function forInRight(object, callback, thisArg) { - var pairs = []; + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); + } else if (fromIndex) { + var index = binaryIndex(array, value), + other = array[index]; - forIn(object, function(value, key) { - pairs.push(key, value); - }); - - var length = pairs.length; - callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - if (callback(pairs[length--], pairs[length], object) === false) { - break; - } + return (value === value ? value === other : other !== other) ? index : -1; } - return object; + return baseIndexOf(array, value, fromIndex); } /** - * Iterates over own enumerable properties of an object, executing the callback - * for each property. The callback is bound to `thisArg` and invoked with three - * arguments; (value, key, object). Callbacks may exit iteration early by - * explicitly returning `false`. + * Gets all but the last element of `array`. * * @static * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. * @example * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) + * _.initial([1, 2, 3]); + * // => [1, 2] */ - var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions); + function initial(array) { + return dropRight(array, 1); + } /** - * This method is like `_.forOwn` except that it iterates over elements - * of a `collection` in the opposite order. + * Creates an array of unique values in all provided arrays using `SameValueZero` + * for equality comparisons. * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of shared values. * @example * - * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' + * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); + * // => [1, 2] */ - function forOwnRight(object, callback, thisArg) { - var props = keys(object), - length = props.length; + function intersection() { + var args = [], + argsIndex = -1, + argsLength = arguments.length, + caches = [], + indexOf = getIndexOf(), + isCommon = indexOf == baseIndexOf; - callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - var key = props[length]; - if (callback(object[key], key, object) === false) { - break; + while (++argsIndex < argsLength) { + var value = arguments[argsIndex]; + if (isArray(value) || isArguments(value)) { + args.push(value); + caches.push(isCommon && value.length >= 120 && createCache(argsIndex && value)); } } - return object; + argsLength = args.length; + var array = args[0], + index = -1, + length = array ? array.length : 0, + result = [], + seen = caches[0]; + + outer: + while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value)) < 0) { + argsIndex = argsLength; + while (--argsIndex) { + var cache = caches[argsIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; } /** - * Creates a sorted array of property names of all enumerable properties, - * own and inherited, of `object` that have function values. + * Gets the last element of `array`. * * @static * @memberOf _ - * @alias methods - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names that have function values. + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. * @example * - * _.functions(_); - * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + * _.last([1, 2, 3]); + * // => 3 */ - function functions(object) { - var result = []; - forIn(object, function(value, key) { - if (isFunction(value)) { - result.push(key); - } - }); - return result.sort(); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; } /** - * Checks if the specified property name exists as a direct property of `object`, - * instead of an inherited property. + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @param {string} key The name of the property to check. - * @returns {boolean} Returns `true` if key is a direct property, else `false`. + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {boolean|number} [fromIndex=array.length-1] The index to search from + * or `true` to perform a binary search on a sorted array. + * @returns {number} Returns the index of the matched value, else `-1`. * @example * - * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); - * // => true + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); + * // => 4 + * + * // using `fromIndex` + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 1 + * + * // performing a binary search + * _.lastIndexOf([4, 4, 5, 5, 6, 6], 5, true); + * // => 3 */ - function has(object, key) { - return object ? hasOwnProperty.call(object, key) : false; + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + return (value === value ? value === other : other !== other) ? index : -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; } /** - * Creates an object composed of the inverted keys and values of the given object. + * Removes all provided values from `array` using `SameValueZero` for equality + * comparisons. * + * **Notes:** + * - Unlike `_.without`, this method mutates `array`. + * - `SameValueZero` comparisons are like strict equality comparisons, e.g. `===`, + * except that `NaN` matches `NaN`. See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to invert. - * @returns {Object} Returns the created inverted object. + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. * @example * - * _.invert({ 'first': 'fred', 'second': 'barney' }); - * // => { 'fred': 'first', 'barney': 'second' } + * var array = [1, 2, 3, 1, 2, 3]; + * _.pull(array, 2, 3); + * console.log(array); + * // => [1, 1] */ - function invert(object) { - var index = -1, - props = keys(object), - length = props.length, - result = {}; + function pull() { + var array = arguments[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, + indexOf = getIndexOf(), + length = arguments.length; while (++index < length) { - var key = props[index]; - result[object[key]] = key; + var fromIndex = 0, + value = arguments[index]; + + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } } - return result; + return array; } /** - * Checks if `value` is a boolean value. + * Removes elements from `array` corresponding to the given indexes and returns + * an array of the removed elements. Indexes may be specified as an array of + * indexes or as individual arguments. * + * **Note:** Unlike `_.at`, this method mutates `array`. + * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`. + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove, + * specified as individual indexes or arrays of indexes. + * @returns {Array} Returns the new array of removed elements. * @example * - * _.isBoolean(null); - * // => false + * var array = [5, 10, 15, 20]; + * var evens = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => [5, 15] + * + * console.log(evens); + * // => [10, 20] */ - function isBoolean(value) { - return value === true || value === false || - value && typeof value == 'object' && toString.call(value) == boolClass || false; + function pullAt(array) { + return basePullAt(array || [], baseFlatten(arguments, false, false, 1)); } /** - * Checks if `value` is a date. + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * **Note:** Unlike `_.filter`, this method mutates `array`. + * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a date, else `false`. + * @category Array + * @param {Array} array The array to modify. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new array of removed elements. * @example * - * _.isDate(new Date); - * // => true + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { return n % 2 == 0; }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] */ - function isDate(value) { - return value && typeof value == 'object' && toString.call(value) == dateClass || false; + function remove(array, predicate, thisArg) { + var index = -1, + length = array ? array.length : 0, + result = []; + + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + splice.call(array, index--, 1); + length--; + } + } + return result; } /** - * Checks if `value` is a DOM element. + * Gets all but the first element of `array`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`. + * @alias tail + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. * @example * - * _.isElement(document.body); - * // => true + * _.rest([1, 2, 3]); + * // => [2, 3] */ - function isElement(value) { - return value && value.nodeType === 1 || false; + function rest(array) { + return drop(array, 1); } /** - * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a - * length of `0` and objects with no own enumerable properties are considered - * "empty". + * Creates a slice of `array` from `start` up to, but not including, `end`. * + * **Note:** This function is used instead of `Array#slice` to support node + * lists in IE < 9 and to ensure dense arrays are returned. + * * @static * @memberOf _ - * @category Objects - * @param {Array|Object|string} value The value to inspect. - * @returns {boolean} Returns `true` if the `value` is empty, else `false`. - * @example - * - * _.isEmpty([1, 2, 3]); - * // => false - * - * _.isEmpty({}); - * // => true - * - * _.isEmpty(''); - * // => true + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. */ - function isEmpty(value) { - var result = true; - if (!value) { - return result; + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; } - var className = toString.call(value), - length = value.length; - - if ((className == arrayClass || className == stringClass || - (support.argsClass ? className == argsClass : isArguments(value))) || - (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { - return !length; + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; } - forOwn(value, function() { - return (result = false); - }); - return result; + return baseSlice(array, start, end); } /** - * Performs a deep comparison between two values to determine if they are - * equivalent to each other. If a callback is provided it will be executed - * to compare values. If the callback returns `undefined` comparisons will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (a, b). + * Uses a binary search to determine the lowest index at which `value` should + * be inserted into `array` in order to maintain its sort order. If an iteratee + * function is provided it is invoked for `value` and each element of `array` + * to compute their sort ranking. The iteratee is bound to `thisArg` and + * invoked with one argument; (value). * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Objects - * @param {*} a The value to compare. - * @param {*} b The other value to compare. - * @param {Function} [callback] The function to customize comparing values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. * @example * - * var object = { 'name': 'fred' }; - * var copy = { 'name': 'fred' }; + * _.sortedIndex([30, 50], 40); + * // => 1 * - * object == copy; - * // => false + * _.sortedIndex([4, 4, 5, 5, 6, 6], 5); + * // => 2 * - * _.isEqual(object, copy); - * // => true + * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; * - * var words = ['hello', 'goodbye']; - * var otherWords = ['hi', 'goodbye']; + * // using an iteratee function + * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { + * return this.data[word]; + * }, dict); + * // => 1 * - * _.isEqual(words, otherWords, function(a, b) { - * var reGreet = /^(?:hello|hi)$/i, - * aGreet = _.isString(a) && reGreet.test(a), - * bGreet = _.isString(b) && reGreet.test(b); - * - * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; - * }); - * // => true + * // using the "_.property" callback shorthand + * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); + * // => 1 */ - function isEqual(a, b, callback, thisArg) { - return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2)); + function sortedIndex(array, value, iteratee, thisArg) { + var func = getCallback(iteratee); + return (func === baseCallback && iteratee == null) + ? binaryIndex(array, value) + : binaryIndexBy(array, value, func(iteratee, thisArg, 1)); } /** - * Checks if `value` is, or can be coerced to, a finite number. + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. * - * Note: This is not the same as native `isFinite` which will return true for - * booleans and empty strings. See http://es5.github.io/#x15.1.2.5. - * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is finite, else `false`. + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. * @example * - * _.isFinite(-101); - * // => true - * - * _.isFinite('10'); - * // => true - * - * _.isFinite(true); - * // => false - * - * _.isFinite(''); - * // => false - * - * _.isFinite(Infinity); - * // => false + * _.sortedLastIndex([4, 4, 5, 5, 6, 6], 5); + * // => 4 */ - function isFinite(value) { - return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); + function sortedLastIndex(array, value, iteratee, thisArg) { + var func = getCallback(iteratee); + return (func === baseCallback && iteratee == null) + ? binaryIndex(array, value, true) + : binaryIndexBy(array, value, func(iteratee, thisArg, 1), true); } /** - * Checks if `value` is a function. + * Creates a slice of `array` with `n` elements taken from the beginning. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. + * @type Function + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. * @example * - * _.isFunction(_); - * // => true + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] */ - function isFunction(value) { - return typeof value == 'function'; + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); } - // fallback for older versions of Chrome and Safari - if (isFunction(/x/)) { - isFunction = function(value) { - return typeof value == 'function' && toString.call(value) == funcClass; - }; - } /** - * Checks if `value` is the language type of Object. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * Creates a slice of `array` with `n` elements taken from the end. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. + * @type Function + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. * @example * - * _.isObject({}); - * // => true + * _.takeRight([1, 2, 3]); + * // => [3] * - * _.isObject([1, 2, 3]); - * // => true + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] * - * _.isObject(1); - * // => false + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] */ - function isObject(value) { - // check if the value is the ECMAScript language type of Object - // http://es5.github.io/#x8 - // and avoid a V8 bug - // http://code.google.com/p/v8/issues/detail?id=2291 - return !!(value && objectTypes[typeof value]); + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); } /** - * Checks if `value` is `NaN`. + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is bound to `thisArg` + * and invoked with three arguments; (value, index, array). * - * Note: This is not the same as native `isNaN` which will return `true` for - * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`. + * @type Function + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per element. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. * @example * - * _.isNaN(NaN); - * // => true + * _.takeRightWhile([1, 2, 3], function(n) { return n > 1; }); + * // => [2, 3] * - * _.isNaN(new Number(NaN)); - * // => true + * var users = [ + * { 'user': 'barney', 'status': 'busy', 'active': false }, + * { 'user': 'fred', 'status': 'busy', 'active': true }, + * { 'user': 'pebbles', 'status': 'away', 'active': true } + * ]; * - * isNaN(undefined); - * // => true + * // using the "_.property" callback shorthand + * _.pluck(_.takeRightWhile(users, 'active'), 'user'); + * // => ['fred', 'pebbles'] * - * _.isNaN(undefined); - * // => false + * // using the "_.matches" callback shorthand + * _.pluck(_.takeRightWhile(users, { 'status': 'away' }), 'user'); + * // => ['pebbles'] */ - function isNaN(value) { - // `NaN` as a primitive is the only value that is not equal to itself - // (perform the [[Class]] check first to avoid errors with some host objects in IE) - return isNumber(value) && value != +value; + function takeRightWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + predicate = getCallback(predicate, thisArg, 3); + while (length-- && predicate(array[length], length, array)) {} + return baseSlice(array, length + 1); } /** - * Checks if `value` is `null`. + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `null`, else `false`. + * @type Function + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per element. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. * @example * - * _.isNull(null); - * // => true + * _.takeWhile([1, 2, 3], function(n) { return n < 3; }); + * // => [1, 2] * - * _.isNull(undefined); - * // => false + * var users = [ + * { 'user': 'barney', 'status': 'busy', 'active': true }, + * { 'user': 'fred', 'status': 'busy', 'active': false }, + * { 'user': 'pebbles', 'status': 'away', 'active': true } + * ]; + * + * // using the "_.property" callback shorthand + * _.pluck(_.takeWhile(users, 'active'), 'user'); + * // => ['barney'] + * + * // using the "_.matches" callback shorthand + * _.pluck(_.takeWhile(users, { 'status': 'busy' }), 'user'); + * // => ['barney', 'fred'] */ - function isNull(value) { - return value === null; + function takeWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var index = -1; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) {} + return baseSlice(array, 0, index); } /** - * Checks if `value` is a number. + * Creates an array of unique values, in order, of the provided arrays using + * `SameValueZero` for equality comparisons. * - * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5. + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a number, else `false`. + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. * @example * - * _.isNumber(8.4 * 5); - * // => true + * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); + * // => [1, 2, 3, 5, 4] */ - function isNumber(value) { - return typeof value == 'number' || - value && typeof value == 'object' && toString.call(value) == numberClass || false; + function union() { + return baseUniq(baseFlatten(arguments, false, true)); } /** - * Checks if `value` is an object created by the `Object` constructor. + * Creates a duplicate-value-free version of an array using `SameValueZero` + * for equality comparisons. Providing `true` for `isSorted` performs a faster + * search algorithm for sorted arrays. If an iteratee function is provided it + * is invoked for each value in the array to generate the criterion by which + * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @alias unique + * @category Array + * @param {Array} array The array to inspect. + * @param {boolean} [isSorted] Specify the array is sorted. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * If a property name or object is provided it is used to create a "_.property" + * or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the new duplicate-value-free array. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * _.uniq([1, 2, 1]); + * // => [1, 2] * - * _.isPlainObject(new Shape); - * // => false + * // using `isSorted` + * _.uniq([1, 1, 2], true); + * // => [1, 2] * - * _.isPlainObject([1, 2, 3]); - * // => false + * // using an iteratee function + * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); + * // => [1, 2.5] * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true + * // using the "_.property" callback shorthand + * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) { - return false; + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; } - var valueOf = value.valueOf, - objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + // Juggle arguments. + if (typeof isSorted != 'boolean' && isSorted != null) { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; + isSorted = false; + } + var func = getCallback(); + if (!(func === baseCallback && iteratee == null)) { + iteratee = func(iteratee, thisArg, 3); + } + return (isSorted && getIndexOf() == baseIndexOf) + ? sortedUniq(array, iteratee) + : baseUniq(array, iteratee); + } - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); - }; - /** - * Checks if `value` is a regular expression. + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-`_.zip` + * configuration. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`. + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. * @example * - * _.isRegExp(/fred/); - * // => true + * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); + * // => [['fred', 30, true], ['barney', 40, false]] + * + * _.unzip(zipped); + * // => [['fred', 'barney'], [30, 40], [true, false]] */ - function isRegExp(value) { - return value && objectTypes[typeof value] && toString.call(value) == regexpClass || false; + function unzip(array) { + var index = -1, + length = (array && array.length && arrayMax(arrayMap(array, getLength))) >>> 0, + result = Array(length); + + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; } /** - * Checks if `value` is a string. + * Creates an array excluding all provided values using `SameValueZero` for + * equality comparisons. * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a string, else `false`. + * @category Array + * @param {Array} array The array to filter. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. * @example * - * _.isString('fred'); - * // => true + * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); + * // => [2, 3, 4] */ - function isString(value) { - return typeof value == 'string' || - value && typeof value == 'object' && toString.call(value) == stringClass || false; + function without(array) { + return baseDifference(array, baseSlice(arguments, 1)); } /** - * Checks if `value` is `undefined`. + * Creates an array that is the symmetric difference of the provided arrays. + * See [Wikipedia](https://en.wikipedia.org/wiki/Symmetric_difference) for + * more details. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`. + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of values. * @example * - * _.isUndefined(void 0); - * // => true + * _.xor([1, 2, 3], [5, 2, 1, 4]); + * // => [3, 5, 4] + * + * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); + * // => [1, 4, 5] */ - function isUndefined(value) { - return typeof value == 'undefined'; + function xor() { + var index = -1, + length = arguments.length; + + while (++index < length) { + var array = arguments[index]; + if (isArray(array) || isArguments(array)) { + var result = result + ? baseDifference(result, array).concat(baseDifference(array, result)) + : array; + } + } + return result ? baseUniq(result) : []; } /** - * Creates an object with the same keys as `object` and values generated by - * running each own enumerable property of `object` through the callback. - * The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). + * Creates an array of grouped elements, the first of which contains the first + * elements of the given arrays, the second of which contains the second elements + * of the given arrays, and so on. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new object with values of the results of each `callback` execution. + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. * @example * - * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); - * // => { 'a': 3, 'b': 6, 'c': 9 } - * - * var characters = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; - * - * // using "_.pluck" callback shorthand - * _.mapValues(characters, 'age'); - * // => { 'fred': 40, 'pebbles': 1 } + * _.zip(['fred', 'barney'], [30, 40], [true, false]); + * // => [['fred', 30, true], ['barney', 40, false]] */ - function mapValues(object, callback, thisArg) { - var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); + function zip() { + var length = arguments.length, + array = Array(length); - forOwn(object, function(value, key, object) { - result[key] = callback(value, key, object); - }); - return result; + while (length--) { + array[length] = arguments[length]; + } + return unzip(array); } /** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * will overwrite property assignments of previous sources. If a callback is - * provided it will be executed to produce the merged values of the destination - * and source properties. If the callback returns `undefined` merging will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (objectValue, sourceValue). + * Creates an object composed from arrays of property names and values. Provide + * either a single two dimensional array, e.g. `[[key1, value1], [key2, value2]]` + * or two arrays, one of property names and one of corresponding values. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize merging properties. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. + * @alias object + * @category Array + * @param {Array} props The property names. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. * @example * - * var names = { - * 'characters': [ - * { 'name': 'barney' }, - * { 'name': 'fred' } - * ] - * }; - * - * var ages = { - * 'characters': [ - * { 'age': 36 }, - * { 'age': 40 } - * ] - * }; - * - * _.merge(names, ages); - * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } - * - * var food = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var otherFood = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; - * - * _.merge(food, otherFood, function(a, b) { - * return _.isArray(a) ? a.concat(b) : undefined; - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } + * _.zipObject(['fred', 'barney'], [30, 40]); + * // => { 'fred': 30, 'barney': 40 } */ - function merge(object) { - var args = arguments, - length = 2; + function zipObject(props, values) { + var index = -1, + length = props ? props.length : 0, + result = {}; - if (!isObject(object)) { - return object; + if (length && !values && !isArray(props[0])) { + values = []; } - // allows working with `_.reduce` and `_.reduceRight` without using - // their `index` and `collection` arguments - if (typeof args[2] != 'number') { - length = args.length; - } - if (length > 3 && typeof args[length - 2] == 'function') { - var callback = baseCreateCallback(args[--length - 1], args[length--], 2); - } else if (length > 2 && typeof args[length - 1] == 'function') { - callback = args[--length]; - } - var sources = slice(arguments, 1, length), - index = -1, - stackA = getArray(), - stackB = getArray(); - while (++index < length) { - baseMerge(object, sources[index], callback, stackA, stackB); + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } } - releaseArray(stackA); - releaseArray(stackB); - return object; + return result; } + /*------------------------------------------------------------------------*/ + /** - * Creates a shallow clone of `object` excluding the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` omitting the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). + * Creates a `lodash` object that wraps `value` with explicit method + * chaining enabled. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The properties to omit or the - * function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object without the omitted properties. + * @category Chain + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` object. * @example * - * _.omit({ 'name': 'fred', 'age': 40 }, 'age'); - * // => { 'name': 'fred' } + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; * - * _.omit({ 'name': 'fred', 'age': 40 }, function(value) { - * return typeof value == 'number'; - * }); - * // => { 'name': 'fred' } + * var youngest = _.chain(users) + * .sortBy('age') + * .map(function(chr) { return chr.user + ' is ' + chr.age; }) + * .first() + * .value(); + * // => 'pebbles is 1' */ - function omit(object, callback, thisArg) { - var result = {}; - if (typeof callback != 'function') { - var props = []; - forIn(object, function(value, key) { - props.push(key); - }); - props = baseDifference(props, baseFlatten(arguments, true, false, 1)); - - var index = -1, - length = props.length; - - while (++index < length) { - var key = props[index]; - result[key] = object[key]; - } - } else { - callback = lodash.createCallback(callback, thisArg, 3); - forIn(object, function(value, key, object) { - if (!callback(value, key, object)) { - result[key] = value; - } - }); - } + function chain(value) { + var result = lodash(value); + result.__chain__ = true; return result; } /** - * Creates a two dimensional array of an object's key-value pairs, - * i.e. `[[key1, value1], [key2, value2]]`. + * This method invokes `interceptor` and returns `value`. The interceptor is + * bound to `thisArg` and invoked with one argument; (value). The purpose of + * this method is to "tap into" a method chain in order to perform operations + * on intermediate results within the chain. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns new array of key-value pairs. + * @category Chain + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @param {*} [thisArg] The `this` binding of `interceptor`. + * @returns {*} Returns `value`. * @example * - * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + * _([1, 2, 3]) + * .tap(function(array) { array.pop(); }) + * .reverse() + * .value(); + * // => [2, 1] */ - function pairs(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - var key = props[index]; - result[index] = [key, object[key]]; - } - return result; + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; } /** - * Creates a shallow clone of `object` composed of the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` picking the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). + * This method is like `_.tap` except that it returns the result of `interceptor`. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The function called per - * iteration or property names to pick, specified as individual property - * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object composed of the picked properties. + * @category Chain + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @param {*} [thisArg] The `this` binding of `interceptor`. + * @returns {*} Returns the result of `interceptor`. * @example * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); - * // => { 'name': 'fred' } - * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { - * return key.charAt(0) != '_'; - * }); - * // => { 'name': 'fred' } + * _([1, 2, 3]) + * .last() + * .thru(function(value) { return [value]; }) + * .value(); + * // => [3] */ - function pick(object, callback, thisArg) { - var result = {}; - if (typeof callback != 'function') { - var index = -1, - props = baseFlatten(arguments, true, false, 1), - length = isObject(object) ? props.length : 0; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - } else { - callback = lodash.createCallback(callback, thisArg, 3); - forIn(object, function(value, key, object) { - if (callback(value, key, object)) { - result[key] = value; - } - }); - } - return result; + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); } /** - * An alternative to `_.reduce` this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own - * enumerable properties through a callback, with each callback execution - * potentially mutating the `accumulator` object. The callback is bound to - * `thisArg` and invoked with four arguments; (accumulator, value, key, object). - * Callbacks may exit iteration early by explicitly returning `false`. + * Enables explicit method chaining on the wrapper object. * - * @static + * @name chain * @memberOf _ - * @category Objects - * @param {Array|Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the accumulated value. + * @category Chain + * @returns {*} Returns the `lodash` object. * @example * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; - * } - * }); - * // => [1, 9, 25] + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; - * }); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * // without explicit chaining + * _(users).first(); + * // => { 'user': 'barney', 'age': 36 } + * + * // with explicit chaining + * _(users).chain() + * .first() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } */ - function transform(object, callback, accumulator, thisArg) { - var isArr = isArray(object); - if (accumulator == null) { - if (isArr) { - accumulator = []; - } else { - var ctor = object && object.constructor, - proto = ctor && ctor.prototype; + function wrapperChain() { + return chain(this); + } - accumulator = baseCreate(proto); + /** + * Reverses the wrapped array so the first element becomes the last, the + * second element becomes the second to last, and so on. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new reversed `lodash` object. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + if (this.__actions__.length) { + value = new LazyWrapper(this); } + return new LodashWrapper(value.reverse()); } - if (callback) { - callback = lodash.createCallback(callback, thisArg, 4); - (isArr ? baseEach : forOwn)(object, function(value, index, object) { - return callback(accumulator, value, index, object); - }); - } - return accumulator; + return this.thru(function(value) { + return value.reverse(); + }); } /** - * Creates an array composed of the own enumerable property values of `object`. + * Produces the result of coercing the unwrapped value to a string. * - * @static + * @name toString * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property values. + * @category Chain + * @returns {string} Returns the coerced string value. * @example * - * _.values({ 'one': 1, 'two': 2, 'three': 3 }); - * // => [1, 2, 3] (property order is not guaranteed across environments) + * _([1, 2, 3]).toString(); + * // => '1,2,3' */ - function values(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); + function wrapperToString() { + return (this.value() + ''); + } - while (++index < length) { - result[index] = object[props[index]]; - } - return result; + /** + * Executes the chained sequence to extract the unwrapped value. + * + * @name value + * @memberOf _ + * @alias toJSON, valueOf + * @category Chain + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); } - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** - * Creates an array of elements from the specified indexes, or keys, of the - * `collection`. Indexes may be specified as individual arguments or as arrays - * of indexes. + * Creates an array of elements corresponding to the given keys, or indexes, + * of `collection`. Keys may be specified as individual arguments or as arrays + * of keys. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [index] The indexes of `collection` - * to retrieve, specified as individual indexes or arrays of indexes. - * @returns {Array} Returns a new array of elements corresponding to the - * provided indexes. + * @param {...(number|number[]|string|string[])} [props] The property names + * or indexes of elements to pick, specified individually or in arrays. + * @returns {Array} Returns the new array of picked elements. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); * // => ['a', 'c', 'e'] * * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ function at(collection) { - var args = arguments, - index = -1, - props = baseFlatten(args, true, false, 1), - length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length, - result = Array(length); - - if (support.unindexedChars && isString(collection)) { - collection = collection.split(''); + var length = collection ? collection.length : 0; + if (isLength(length)) { + collection = toIterable(collection); } - while(++index < length) { - result[index] = collection[props[index]]; - } - return result; + return baseAt(collection, baseFlatten(arguments, false, false, 1)); } /** - * Checks if a given value is present in a collection using strict equality - * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. + * Checks if `value` is in `collection` using `SameValueZero` for equality + * comparisons. If `fromIndex` is negative, it is used as the offset from + * the end of `collection`. * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ - * @alias include - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {*} target The value to check for. + * @alias contains, include + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {*} target The value to search for. * @param {number} [fromIndex=0] The index to search from. - * @returns {boolean} Returns `true` if the `target` element is found, else `false`. + * @returns {boolean} Returns `true` if a matching element is found, else `false`. * @example * - * _.contains([1, 2, 3], 1); + * _.includes([1, 2, 3], 1); * // => true * - * _.contains([1, 2, 3], 1, 2); + * _.includes([1, 2, 3], 1, 2); * // => false * - * _.contains({ 'name': 'fred', 'age': 40 }, 'fred'); + * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); * // => true * - * _.contains('pebbles', 'eb'); + * _.includes('pebbles', 'eb'); * // => true */ - function contains(collection, target, fromIndex) { - var index = -1, - indexOf = getIndexOf(), - length = collection ? collection.length : 0, - result = false; - - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; - if (isArray(collection)) { - result = indexOf(collection, target, fromIndex) > -1; - } else if (typeof length == 'number') { - result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1; + function includes(collection, target, fromIndex) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (!length) { + return false; + } + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } else { - baseEach(collection, function(value) { - if (++index >= fromIndex) { - return !(result = value === target); - } - }); + fromIndex = 0; } - return result; + return (typeof collection == 'string' || !isArray(collection) && isString(collection)) + ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) + : (getIndexOf(collection, target, fromIndex) > -1); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through the callback. The corresponding value - * of each key is the number of times the key was returned by the callback. - * The callback is bound to `thisArg` and invoked with three arguments; + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the number of times the key was returned by `iteratee`. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.countBy([4.3, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': 1, '6': 2 } * - * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.countBy([4.3, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { - (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1); + hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); }); /** - * Checks if the given callback returns truey value for **all** elements of - * a collection. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index|key, collection). + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * The predicate is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ * @alias all - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if all elements passed the callback check, + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false`. * @example * * _.every([true, 1, null, 'yes']); * // => false * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } * ]; * - * // using "_.pluck" callback shorthand - * _.every(characters, 'age'); + * // using the "_.property" callback shorthand + * _.every(users, 'age'); * // => true * - * // using "_.where" callback shorthand - * _.every(characters, { 'age': 36 }); + * // using the "_.matches" callback shorthand + * _.every(users, { 'age': 36 }); * // => false */ - function every(collection, callback, thisArg) { - var result = true; - callback = lodash.createCallback(callback, thisArg, 3); - - if (isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - if (!(result = !!callback(collection[index], index, collection))) { - break; - } - } - } else { - baseEach(collection, function(value, index, collection) { - return (result = !!callback(value, index, collection)); - }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (typeof predicate != 'function' || typeof thisArg != 'undefined') { + predicate = getCallback(predicate, thisArg, 3); } - return result; + return func(collection, predicate); } /** - * Iterates over elements of a collection, returning an array of all elements - * the callback returns truey for. The callback is bound to `thisArg` and + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ * @alias select - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of elements that passed the callback check. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new filtered array. * @example * - * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); - * // => [2, 4, 6] + * var evens = _.filter([1, 2, 3, 4], function(n) { return n % 2 == 0; }); + * // => [2, 4] * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true } + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } * ]; * - * // using "_.pluck" callback shorthand - * _.filter(characters, 'blocked'); - * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] + * // using the "_.property" callback shorthand + * _.pluck(_.filter(users, 'active'), 'user'); + * // => ['fred'] * - * // using "_.where" callback shorthand - * _.filter(characters, { 'age': 36 }); - * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }] + * // using the "_.matches" callback shorthand + * _.pluck(_.filter(users, { 'age': 36 }), 'user'); + * // => ['barney'] */ - function filter(collection, callback, thisArg) { - var result = []; - callback = lodash.createCallback(callback, thisArg, 3); - - if (isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - var value = collection[index]; - if (callback(value, index, collection)) { - result.push(value); - } - } - } else { - baseEach(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result.push(value); - } - }); - } - return result; + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); } /** - * Iterates over elements of a collection, returning the first element that - * the callback returns truey for. The callback is bound to `thisArg` and + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @alias detect, findWhere - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the found element, else `undefined`. + * @alias detect + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {*} Returns the matched element, else `undefined`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true }, - * { 'name': 'pebbles', 'age': 1, 'blocked': false } + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } * ]; * - * _.find(characters, function(chr) { - * return chr.age < 40; - * }); - * // => { 'name': 'barney', 'age': 36, 'blocked': false } + * _.result(_.find(users, function(chr) { return chr.age < 40; }), 'user'); + * // => 'barney' * - * // using "_.where" callback shorthand - * _.find(characters, { 'age': 1 }); - * // => { 'name': 'pebbles', 'age': 1, 'blocked': false } + * // using the "_.matches" callback shorthand + * _.result(_.find(users, { 'age': 1 }), 'user'); + * // => 'pebbles' * - * // using "_.pluck" callback shorthand - * _.find(characters, 'blocked'); - * // => { 'name': 'fred', 'age': 40, 'blocked': true } + * // using the "_.property" callback shorthand + * _.result(_.find(users, 'active'), 'user'); + * // => 'fred' */ - function find(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); - + function find(collection, predicate, thisArg) { if (isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - var value = collection[index]; - if (callback(value, index, collection)) { - return value; - } - } - } else { - var result; - baseEach(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result = value; - return false; - } - }); - return result; + var index = findIndex(collection, predicate, thisArg); + return index > -1 ? collection[index] : undefined; } + predicate = getCallback(predicate, thisArg, 3); + return baseFind(collection, predicate, baseEach); } /** - * This method is like `_.find` except that it iterates over elements - * of a `collection` from right to left. + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the found element, else `undefined`. + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {*} Returns the matched element, else `undefined`. * @example * - * _.findLast([1, 2, 3, 4], function(num) { - * return num % 2 == 1; - * }); + * _.findLast([1, 2, 3, 4], function(n) { return n % 2 == 1; }); * // => 3 */ - function findLast(collection, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - forEachRight(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result = value; - return false; - } - }); - return result; + function findLast(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(collection, predicate, baseEachRight); } /** - * Iterates over elements of a collection, executing the callback for each - * element. The callback is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). Callbacks may exit iteration early by - * explicitly returning `false`. + * Performs a deep comparison between each element in `collection` and the + * source object, returning the first element that has equivalent property + * values. * - * Note: As with other "Collections" methods, objects with a `length` property + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Object} source The object of property values to match. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'status': 'busy' }, + * { 'user': 'fred', 'age': 40, 'status': 'busy' } + * ]; + * + * _.result(_.findWhere(users, { 'status': 'busy' }), 'user'); + * // => 'barney' + * + * _.result(_.findWhere(users, { 'age': 40 }), 'user'); + * // => 'fred' + */ + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + + /** + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). Iterator functions may exit iteration early + * by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * * @static * @memberOf _ * @alias each - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); - * // => logs each number and returns '1,2,3' + * _([1, 2, 3]).forEach(function(n) { console.log(n); }).value(); + * // => logs each value from left to right and returns the array * - * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); - * // => logs each number and returns the object (property order is not guaranteed across environments) + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); + * // => logs each value-key pair and returns the object (iteration order is not guaranteed) */ - function forEach(collection, callback, thisArg) { - if (callback && typeof thisArg == 'undefined' && isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - if (callback(collection[index], index, collection) === false) { - break; - } - } - } else { - baseEach(collection, callback, thisArg); - } - return collection; + function forEach(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEach(collection, iteratee) + : baseEach(collection, bindCallback(iteratee, thisArg, 3)); } /** - * This method is like `_.forEach` except that it iterates over elements - * of a `collection` from right to left. + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. * * @static * @memberOf _ * @alias eachRight - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); - * // => logs each number from right to left and returns '3,2,1' + * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); + * // => logs each value from right to left and returns the array */ - function forEachRight(collection, callback, thisArg) { - var iterable = collection, - length = collection ? collection.length : 0; - - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - if (isArray(collection)) { - while (length--) { - if (callback(collection[length], length, collection) === false) { - break; - } - } - } else { - if (typeof length != 'number') { - var props = keys(collection); - length = props.length; - } else if (support.unindexedChars && isString(collection)) { - iterable = collection.split(''); - } - baseEach(collection, function(value, key, collection) { - key = props ? props[--length] : --length; - return callback(iterable[key], key, collection); - }); - } - return collection; + function forEachRight(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEachRight(collection, iteratee) + : baseEachRight(collection, bindCallback(iteratee, thisArg, 3)); } /** * Creates an object composed of keys generated from the results of running - * each element of a collection through the callback. The corresponding value + * each element of `collection` through `iteratee`. The corresponding value * of each key is an array of the elements responsible for generating the key. - * The callback is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false` + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * - * // using "_.pluck" callback shorthand + * // using the "_.property" callback shorthand * _.groupBy(['one', 'two', 'three'], 'length'); * // => { '3': ['one', 'two'], '5': ['three'] } */ var groupBy = createAggregator(function(result, value, key) { - (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value); + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [value]; + } }); /** * Creates an object composed of keys generated from the results of running - * each element of the collection through the given callback. The corresponding - * value of each key is the last element responsible for generating the key. - * The callback is bound to `thisArg` and invoked with three arguments; + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the last element responsible for generating the key. The + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * - * var keys = [ + * var keyData = [ * { 'dir': 'left', 'code': 97 }, * { 'dir': 'right', 'code': 100 } * ]; * - * _.indexBy(keys, 'dir'); + * _.indexBy(keyData, 'dir'); * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } * - * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); }); + * _.indexBy(keyData, function(object) { return String.fromCharCode(object.code); }); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } * - * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String); + * _.indexBy(keyData, function(object) { return this.fromCharCode(object.code); }, String); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } */ var indexBy = createAggregator(function(result, value, key) { result[key] = value; }); /** - * Invokes the method named by `methodName` on each element in the `collection` - * returning an array of the results of each invoked method. Additional arguments - * will be provided to each invoked method. If `methodName` is a function it - * will be invoked for, and `this` bound to, each element in the `collection`. + * Invokes the method named by `methodName` on each element in `collection`, + * returning an array of the results of each invoked method. Any additional + * arguments are provided to each invoked method. If `methodName` is a function + * it is invoked for, and `this` bound to, each element in `collection`. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. - * @param {...*} [arg] Arguments to invoke the method with. - * @returns {Array} Returns a new array of the results of each invoked method. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {Array} Returns the array of results. * @example * * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); * // => [[1, 5, 7], [1, 2, 3]] * * _.invoke([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ function invoke(collection, methodName) { - var args = slice(arguments, 2), - index = -1, - isFunc = typeof methodName == 'function', - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); - - forEach(collection, function(value) { - result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); - }); - return result; + return baseInvoke(collection, methodName, baseSlice(arguments, 2)); } /** - * Creates an array of values by running each element in the collection - * through the callback. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). + * Creates an array of values by running each element in `collection` through + * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ * @alias collect - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of the results of each `callback` execution. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the new mapped array. * @example * - * _.map([1, 2, 3], function(num) { return num * 3; }); + * _.map([1, 2, 3], function(n) { return n * 3; }); * // => [3, 6, 9] * - * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); - * // => [3, 6, 9] (property order is not guaranteed across environments) + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); + * // => [3, 6, 9] (iteration order is not guaranteed) * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } * ]; * - * // using "_.pluck" callback shorthand - * _.map(characters, 'name'); + * // using the "_.property" callback shorthand + * _.map(users, 'user'); * // => ['barney', 'fred'] */ - function map(collection, callback, thisArg) { - var index = -1, - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); - - callback = lodash.createCallback(callback, thisArg, 3); - if (isArray(collection)) { - while (++index < length) { - result[index] = callback(collection[index], index, collection); - } - } else { - baseEach(collection, function(value, key, collection) { - result[++index] = callback(value, key, collection); - }); - } - return result; + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); } /** - * Retrieves the maximum value of a collection. If the collection is empty or - * falsey `-Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Gets the maximum value of `collection`. If `collection` is empty or falsey + * `-Infinity` is returned. If an iteratee function is provided it is invoked + * for each value in `collection` to generate the criterion by which the value + * is ranked. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * If a property name or object is provided it is used to create a "_.property" + * or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the maximum value. * @example * * _.max([4, 2, 8, 6]); * // => 8 * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * _.max([]); + * // => -Infinity + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } * ]; * - * _.max(characters, function(chr) { return chr.age; }); - * // => { 'name': 'fred', 'age': 40 }; + * _.max(users, function(chr) { return chr.age; }); + * // => { 'user': 'fred', 'age': 40 }; * - * // using "_.pluck" callback shorthand - * _.max(characters, 'age'); - * // => { 'name': 'fred', 'age': 40 }; + * // using the "_.property" callback shorthand + * _.max(users, 'age'); + * // => { 'user': 'fred', 'age': 40 }; */ - function max(collection, callback, thisArg) { - var computed = -Infinity, - result = computed; + var max = createExtremum(arrayMax); - // allows working with functions like `_.map` without using - // their `index` argument as a callback - if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) { - callback = null; - } - if (callback == null && isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - var value = collection[index]; - if (value > result) { - result = value; - } - } - } else { - callback = (callback == null && isString(collection)) - ? charAtCallback - : lodash.createCallback(callback, thisArg, 3); - - baseEach(collection, function(value, index, collection) { - var current = callback(value, index, collection); - if (current > computed) { - computed = current; - result = value; - } - }); - } - return result; - } - /** - * Retrieves the minimum value of a collection. If the collection is empty or - * falsey `Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Gets the minimum value of `collection`. If `collection` is empty or falsey + * `Infinity` is returned. If an iteratee function is provided it is invoked + * for each value in `collection` to generate the criterion by which the value + * is ranked. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * If a property name or object is provided it is used to create a "_.property" + * or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the minimum value. * @example * * _.min([4, 2, 8, 6]); * // => 2 * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * _.min([]); + * // => Infinity + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } * ]; * - * _.min(characters, function(chr) { return chr.age; }); - * // => { 'name': 'barney', 'age': 36 }; + * _.min(users, function(chr) { return chr.age; }); + * // => { 'user': 'barney', 'age': 36 }; * - * // using "_.pluck" callback shorthand - * _.min(characters, 'age'); - * // => { 'name': 'barney', 'age': 36 }; + * // using the "_.property" callback shorthand + * _.min(users, 'age'); + * // => { 'user': 'barney', 'age': 36 }; */ - function min(collection, callback, thisArg) { - var computed = Infinity, - result = computed; + var min = createExtremum(arrayMin, true); - // allows working with functions like `_.map` without using - // their `index` argument as a callback - if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) { - callback = null; - } - if (callback == null && isArray(collection)) { - var index = -1, - length = collection.length; + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, while the second of which + * contains elements `predicate` returns falsey for. The predicate is bound + * to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * _.partition([1, 2, 3], function(n) { return n % 2; }); + * // => [[1, 3], [2]] + * + * _.partition([1.2, 2.3, 3.4], function(n) { return this.floor(n) % 2; }, Math); + * // => [[1, 3], [2]] + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * // using the "_.matches" callback shorthand + * _.map(_.partition(users, { 'age': 1 }), function(array) { return _.pluck(array, 'user'); }); + * // => [['pebbles'], ['barney', 'fred']] + * + * // using the "_.property" callback shorthand + * _.map(_.partition(users, 'active'), function(array) { return _.pluck(array, 'user'); }); + * // => [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); - while (++index < length) { - var value = collection[index]; - if (value < result) { - result = value; - } - } - } else { - callback = (callback == null && isString(collection)) - ? charAtCallback - : lodash.createCallback(callback, thisArg, 3); - - baseEach(collection, function(value, index, collection) { - var current = callback(value, index, collection); - if (current < computed) { - computed = current; - result = value; - } - }); - } - return result; - } - /** - * Retrieves the value of a specified property from all elements in the collection. + * Gets the value of `key` from all elements in `collection`. * * @static * @memberOf _ - * @type Function - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {string} property The name of the property to pluck. - * @returns {Array} Returns a new array of property values. + * @param {string} key The key of the property to pluck. + * @returns {Array} Returns the property values. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } * ]; * - * _.pluck(characters, 'name'); + * _.pluck(users, 'user'); * // => ['barney', 'fred'] + * + * var userIndex = _.indexBy(users, 'user'); + * _.pluck(userIndex, 'age'); + * // => [36, 40] (iteration order is not guaranteed) */ - var pluck = map; + function pluck(collection, key) { + return map(collection, baseProperty(key + '')); + } /** - * Reduces a collection to a value which is the accumulated result of running - * each element in the collection through the callback, where each successive - * callback execution consumes the return value of the previous execution. If - * `accumulator` is not provided the first element of the collection will be - * used as the initial `accumulator` value. The callback is bound to `thisArg` - * and invoked with four arguments; (accumulator, value, index|key, collection). + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` through `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not provided the first element of `collection` is used as the initial + * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; + * (accumulator, value, index|key, collection). * * @static * @memberOf _ * @alias foldl, inject - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] Initial value of the accumulator. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * - * var sum = _.reduce([1, 2, 3], function(sum, num) { - * return sum + num; - * }); + * var sum = _.reduce([1, 2, 3], function(sum, n) { return sum + n; }); * // => 6 * - * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * return result; * }, {}); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * // => { 'a': 3, 'b': 6, 'c': 9 } (iteration order is not guaranteed) */ - function reduce(collection, callback, accumulator, thisArg) { - var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); - - if (isArray(collection)) { - var index = -1, - length = collection.length; - - if (noaccum) { - accumulator = collection[++index]; - } - while (++index < length) { - accumulator = callback(accumulator, collection[index], index, collection); - } - } else { - baseEach(collection, function(value, index, collection) { - accumulator = noaccum - ? (noaccum = false, value) - : callback(accumulator, value, index, collection) - }); - } - return accumulator; + function reduce(collection, iteratee, accumulator, thisArg) { + var func = isArray(collection) ? arrayReduce : baseReduce; + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** - * This method is like `_.reduce` except that it iterates over elements - * of a `collection` from right to left. + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. * * @static * @memberOf _ * @alias foldr - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] Initial value of the accumulator. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * - * var list = [[0, 1], [2, 3], [4, 5]]; - * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); + * var array = [[0, 1], [2, 3], [4, 5]]; + * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ - function reduceRight(collection, callback, accumulator, thisArg) { - var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); - forEachRight(collection, function(value, index, collection) { - accumulator = noaccum - ? (noaccum = false, value) - : callback(accumulator, value, index, collection); - }); - return accumulator; + function reduceRight(collection, iteratee, accumulator, thisArg) { + var func = isArray(collection) ? arrayReduceRight : baseReduce; + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); } /** - * The opposite of `_.filter` this method returns the elements of a - * collection that the callback does **not** return truey for. + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of elements that failed the callback check. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new filtered array. * @example * - * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); - * // => [1, 3, 5] + * var odds = _.reject([1, 2, 3, 4], function(n) { return n % 2 == 0; }); + * // => [1, 3] * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true } + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } * ]; * - * // using "_.pluck" callback shorthand - * _.reject(characters, 'blocked'); - * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }] + * // using the "_.property" callback shorthand + * _.pluck(_.reject(users, 'active'), 'user'); + * // => ['barney'] * - * // using "_.where" callback shorthand - * _.reject(characters, { 'age': 36 }); - * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] + * // using the "_.matches" callback shorthand + * _.pluck(_.reject(users, { 'age': 36 }), 'user'); + * // => ['fred'] */ - function reject(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); - return filter(collection, function(value, index, collection) { - return !callback(value, index, collection); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); }); } /** - * Retrieves a random element or `n` random elements from a collection. + * Gets a random element or `n` random elements from a collection. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to sample. * @param {number} [n] The number of elements to sample. - * @param- {Object} [guard] Allows working with functions like `_.map` - * without using their `index` arguments as `n`. - * @returns {Array} Returns the random sample(s) of `collection`. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {*} Returns the random sample(s). * @example * * _.sample([1, 2, 3, 4]); * // => 2 * * _.sample([1, 2, 3, 4], 2); * // => [3, 1] */ function sample(collection, n, guard) { - if (collection && typeof collection.length != 'number') { - collection = values(collection); - } else if (support.unindexedChars && isString(collection)) { - collection = collection.split(''); + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; } - if (n == null || guard) { - return collection ? collection[baseRandom(0, collection.length - 1)] : undefined; - } var result = shuffle(collection); - result.length = nativeMin(nativeMax(0, n), result.length); + result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length); return result; } /** * Creates an array of shuffled values, using a version of the Fisher-Yates - * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle. + * shuffle. See [Wikipedia](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle) + * for more details. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to shuffle. - * @returns {Array} Returns a new shuffled collection. + * @returns {Array} Returns the new shuffled array. * @example * - * _.shuffle([1, 2, 3, 4, 5, 6]); - * // => [4, 1, 6, 3, 5, 2] + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] */ function shuffle(collection) { + collection = toIterable(collection); + var index = -1, - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); + length = collection.length, + result = Array(length); - forEach(collection, function(value) { - var rand = baseRandom(0, ++index); - result[index] = result[rand]; - result[rand] = value; - }); + while (++index < length) { + var rand = baseRandom(0, index); + if (index != rand) { + result[index] = result[rand]; + } + result[rand] = collection[index]; + } return result; } /** - * Gets the size of the `collection` by returning `collection.length` for arrays - * and array-like objects or the number of own enumerable properties for objects. + * Gets the size of `collection` by returning `collection.length` for + * array-like values or the number of own enumerable properties for objects. * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to inspect. - * @returns {number} Returns `collection.length` or number of own enumerable properties. + * @returns {number} Returns the size of `collection`. * @example * * _.size([1, 2]); * // => 2 * @@ -4244,2166 +6426,2804 @@ * _.size('pebbles'); * // => 7 */ function size(collection) { var length = collection ? collection.length : 0; - return typeof length == 'number' ? length : keys(collection).length; + return isLength(length) ? length : keys(collection).length; } /** - * Checks if the callback returns a truey value for **any** element of a - * collection. The function returns as soon as it finds a passing value and - * does not iterate over the entire collection. The callback is bound to - * `thisArg` and invoked with three arguments; (value, index|key, collection). + * Checks if `predicate` returns truthy for **any** element of `collection`. + * The function returns as soon as it finds a passing value and does not iterate + * over the entire collection. The predicate is bound to `thisArg` and invoked + * with three arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ * @alias any - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if any element passed the callback check, + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. * @example * * _.some([null, 0, 'yes', false], Boolean); * // => true * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true } + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } * ]; * - * // using "_.pluck" callback shorthand - * _.some(characters, 'blocked'); + * // using the "_.property" callback shorthand + * _.some(users, 'active'); * // => true * - * // using "_.where" callback shorthand - * _.some(characters, { 'age': 1 }); + * // using the "_.matches" callback shorthand + * _.some(users, { 'age': 1 }); * // => false */ - function some(collection, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - - if (isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - if ((result = callback(collection[index], index, collection))) { - break; - } - } - } else { - baseEach(collection, function(value, index, collection) { - return !(result = callback(value, index, collection)); - }); + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (typeof predicate != 'function' || typeof thisArg != 'undefined') { + predicate = getCallback(predicate, thisArg, 3); } - return !!result; + return func(collection, predicate); } /** * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection through the callback. This method - * performs a stable sort, that is, it will preserve the original sort order - * of equal elements. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). + * running each element in a collection through `iteratee`. This method performs + * a stable sort, that is, it preserves the original sort order of equal elements. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. * - * If an array of property names is provided for `callback` the collection - * will be sorted by each property value. + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * * @static * @memberOf _ - * @category Collections + * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of sorted elements. + * @param {Array|Function|Object|string} [iteratee=_.identity] The function + * invoked per iteration. If a property name or an object is provided it is + * used to create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the new sorted array. * @example * - * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * _.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); * // => [3, 1, 2] * - * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * _.sortBy([1, 2, 3], function(n) { return this.sin(n); }, Math); * // => [3, 1, 2] * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 }, - * { 'name': 'barney', 'age': 26 }, - * { 'name': 'fred', 'age': 30 } + * var users = [ + * { 'user': 'fred' }, + * { 'user': 'pebbles' }, + * { 'user': 'barney' } * ]; * - * // using "_.pluck" callback shorthand - * _.map(_.sortBy(characters, 'age'), _.values); - * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]] - * - * // sorting by multiple properties - * _.map(_.sortBy(characters, ['name', 'age']), _.values); - * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] + * // using the "_.property" callback shorthand + * _.pluck(_.sortBy(users, 'user'), 'user'); + * // => ['barney', 'fred', 'pebbles'] */ - function sortBy(collection, callback, thisArg) { + function sortBy(collection, iteratee, thisArg) { var index = -1, - isArr = isArray(callback), length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); + result = isLength(length) ? Array(length) : []; - if (!isArr) { - callback = lodash.createCallback(callback, thisArg, 3); + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = null; } - forEach(collection, function(value, key, collection) { - var object = result[++index] = getObject(); - if (isArr) { - object.criteria = map(callback, function(key) { return value[key]; }); - } else { - (object.criteria = getArray())[0] = callback(value, key, collection); - } - object.index = index; - object.value = value; + iteratee = getCallback(iteratee, thisArg, 3); + baseEach(collection, function(value, key, collection) { + result[++index] = { 'criteria': iteratee(value, key, collection), 'index': index, 'value': value }; }); - - length = result.length; - result.sort(compareAscending); - while (length--) { - var object = result[length]; - result[length] = object.value; - if (!isArr) { - releaseArray(object.criteria); - } - releaseObject(object); - } - return result; + return baseSortBy(result, compareAscending); } /** - * Converts the `collection` to an array. + * This method is like `_.sortBy` except that it sorts by property names + * instead of an iteratee function. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to convert. - * @returns {Array} Returns the new converted array. + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {...(string|string[])} props The property names to sort by, + * specified as individual property names or arrays of property names. + * @returns {Array} Returns the new sorted array. * @example * - * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); - * // => [2, 3, 4] + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 26 }, + * { 'user': 'fred', 'age': 30 } + * ]; + * + * _.map(_.sortByAll(users, ['user', 'age']), _.values); + * // => [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ - function toArray(collection) { - if (collection && typeof collection.length == 'number') { - return (support.unindexedChars && isString(collection)) - ? collection.split('') - : slice(collection); + function sortByAll(collection) { + var args = arguments; + if (args.length > 3 && isIterateeCall(args[1], args[2], args[3])) { + args = [collection, args[1]]; } - return values(collection); + var index = -1, + length = collection ? collection.length : 0, + props = baseFlatten(args, false, false, 1), + result = isLength(length) ? Array(length) : []; + + baseEach(collection, function(value, key, collection) { + var length = props.length, + criteria = Array(length); + + while (length--) { + criteria[length] = value == null ? undefined : value[props[length]]; + } + result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; + }); + return baseSortBy(result, compareMultipleAscending); } /** - * Performs a deep comparison of each element in a `collection` to the given - * `properties` object, returning an array of all elements that have equivalent + * Performs a deep comparison between each element in `collection` and the + * source object, returning an array of all elements that have equivalent * property values. * * @static * @memberOf _ - * @type Function - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Object} props The object of property values to filter by. - * @returns {Array} Returns a new array of elements that have the given properties. + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Object} source The object of property values to match. + * @returns {Array} Returns the new filtered array. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } + * var users = [ + * { 'user': 'barney', 'age': 36, 'status': 'busy', 'pets': ['hoppy'] }, + * { 'user': 'fred', 'age': 40, 'status': 'busy', 'pets': ['baby puss', 'dino'] } * ]; * - * _.where(characters, { 'age': 36 }); - * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }] + * _.pluck(_.where(users, { 'age': 36 }), 'user'); + * // => ['barney'] * - * _.where(characters, { 'pets': ['dino'] }); - * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }] + * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user'); + * // => ['fred'] + * + * _.pluck(_.where(users, { 'status': 'busy' }), 'user'); + * // => ['barney', 'fred'] */ - var where = filter; + function where(collection, source) { + return filter(collection, baseMatches(source)); + } - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** - * Creates an array with all falsey values removed. The values `false`, `null`, - * `0`, `""`, `undefined`, and `NaN` are all falsey. + * Gets the number of milliseconds that have elapsed since the Unix epoch + * (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to compact. - * @returns {Array} Returns a new array of filtered values. + * @category Date * @example * - * _.compact([0, 1, false, 2, '', 3]); - * // => [1, 2, 3] + * _.defer(function(stamp) { console.log(_.now() - stamp); }, _.now()); + * // => logs the number of milliseconds it took for the deferred function to be invoked */ - function compact(array) { - var index = -1, - length = array ? array.length : 0, - result = []; + var now = nativeNow || function() { + return new Date().getTime(); + }; - while (++index < length) { - var value = array[index]; - if (value) { - result.push(value); + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it is called `n` or more times. + * + * @static + * @memberOf _ + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => logs 'done saving!' after the two async saves have completed + */ + function after(n, func) { + if (!isFunction(func)) { + if (isFunction(n)) { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); } } - return result; + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates a function that accepts up to `n` arguments ignoring any + * additional arguments. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to process. - * @param {...Array} [values] The arrays of values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Function} Returns the new function. * @example * - * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); - * // => [1, 3, 4] + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] */ - function difference(array) { - return baseDifference(array, baseFlatten(arguments, true, true, 1)); + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = null; + } + n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, null, null, null, null, n); } /** - * This method is like `_.find` except that it returns the index of the first - * element that passes the callback check, instead of the element itself. + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it is called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * @static + * @memberOf _ + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * jQuery('#add').on('click', _.before(5, addContactToList)); + * // => allows adding up to 4 contacts to the list + */ + function before(n, func) { + var result; + if (!isFunction(func)) { + if (isFunction(n)) { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } else { + func = null; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and prepends any additional `_.bind` arguments to those provided to the + * bound function. * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind` this method does not set the `length` + * property of bound functions. + * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index of the found element, else `-1`. + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true }, - * { 'name': 'pebbles', 'age': 1, 'blocked': false } - * ]; + * var greet = function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * }; * - * _.findIndex(characters, function(chr) { - * return chr.age < 20; - * }); - * // => 2 + * var object = { 'user': 'fred' }; * - * // using "_.where" callback shorthand - * _.findIndex(characters, { 'age': 36 }); - * // => 0 + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' * - * // using "_.pluck" callback shorthand - * _.findIndex(characters, 'blocked'); - * // => 1 + * // using placeholders + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' */ - function findIndex(array, callback, thisArg) { - var index = -1, - length = array ? array.length : 0; + function bind(func, thisArg) { + var bitmask = BIND_FLAG; + if (arguments.length > 2) { + var partials = baseSlice(arguments, 2), + holders = replaceHolders(partials, bind.placeholder); - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length) { - if (callback(array[index], index, array)) { - return index; - } + bitmask |= PARTIAL_FLAG; } - return -1; + return createWrapper(func, bitmask, thisArg, partials, holders); } /** - * This method is like `_.findIndex` except that it iterates over elements - * of a `collection` from right to left. + * Binds methods of an object to the object itself, overwriting the existing + * method. Method names may be specified as individual arguments or as arrays + * of method names. If no method names are provided all enumerable function + * properties, own and inherited, of `object` are bound. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * **Note:** This method does not set the `length` property of bound functions. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index of the found element, else `-1`. + * @category Function + * @param {Object} object The object to bind and assign the bound methods to. + * @param {...(string|string[])} [methodNames] The object method names to bind, + * specified as individual method names or arrays of method names. + * @returns {Object} Returns `object`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': true }, - * { 'name': 'fred', 'age': 40, 'blocked': false }, - * { 'name': 'pebbles', 'age': 1, 'blocked': true } - * ]; + * var view = { + * 'label': 'docs', + * 'onClick': function() { console.log('clicked ' + this.label); } + * }; * - * _.findLastIndex(characters, function(chr) { - * return chr.age > 30; - * }); - * // => 1 - * - * // using "_.where" callback shorthand - * _.findLastIndex(characters, { 'age': 36 }); - * // => 0 - * - * // using "_.pluck" callback shorthand - * _.findLastIndex(characters, 'blocked'); - * // => 2 + * _.bindAll(view); + * jQuery('#docs').on('click', view.onClick); + * // => logs 'clicked docs' when the element is clicked */ - function findLastIndex(array, callback, thisArg) { - var length = array ? array.length : 0; - callback = lodash.createCallback(callback, thisArg, 3); - while (length--) { - if (callback(array[length], length, array)) { - return length; - } - } - return -1; + function bindAll(object) { + return baseBindAll(object, + arguments.length > 1 + ? baseFlatten(arguments, false, false, 1) + : functions(object) + ); } /** - * Gets the first element or first `n` elements of an array. If a callback - * is provided elements at the beginning of the array are returned as long - * as the callback returns truey. The callback is bound to `thisArg` and - * invoked with three arguments; (value, index, array). + * Creates a function that invokes the method at `object[key]` and prepends + * any additional `_.bindKey` arguments to those provided to the bound function. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. + * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) + * for more details. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. * * @static * @memberOf _ - * @alias head, take - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the first element(s) of `array`. + * @category Function + * @param {Object} object The object the method belongs to. + * @param {string} key The key of the method. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. * @example * - * _.first([1, 2, 3]); - * // => 1 + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; * - * _.first([1, 2, 3], 2); - * // => [1, 2] + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' * - * _.first([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [1, 2] + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; * - * var characters = [ - * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * bound('!'); + * // => 'hiya fred!' * - * // using "_.pluck" callback shorthand - * _.first(characters, 'blocked'); - * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }] - * - * // using "_.where" callback shorthand - * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); - * // => ['barney', 'fred'] + * // using placeholders + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' */ - function first(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; + function bindKey(object, key) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (arguments.length > 2) { + var partials = baseSlice(arguments, 2), + holders = replaceHolders(partials, bindKey.placeholder); - if (typeof callback != 'number' && callback != null) { - var index = -1; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { - n++; - } - } else { - n = callback; - if (n == null || thisArg) { - return array ? array[0] : undefined; - } + bitmask |= PARTIAL_FLAG; } - return slice(array, 0, nativeMin(nativeMax(0, n), length)); + return createWrapper(key, bitmask, object, partials, holders); } /** - * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truey, the array will only be flattened a single level. If a callback - * is provided each element of the array is passed through the callback before - * flattening. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). + * Creates a function that accepts one or more arguments of `func` that when + * called either invokes `func` returning its result, if all `func` arguments + * have been provided, or returns a function that accepts one or more of the + * remaining `func` arguments, and so on. The arity of `func` may be specified + * if `func.length` is not sufficient. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new flattened array. + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Function} Returns the new curried function. * @example * - * _.flatten([1, [2], [3, [[4]]]]); - * // => [1, 2, 3, 4]; + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; * - * _.flatten([1, [2], [3, [[4]]]], true); - * // => [1, 2, 3, [[4]]]; + * var curried = _.curry(abc); * - * var characters = [ - * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } - * ]; + * curried(1)(2)(3); + * // => [1, 2, 3] * - * // using "_.pluck" callback shorthand - * _.flatten(characters, 'pets'); - * // => ['hoppy', 'baby puss', 'dino'] + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // using placeholders + * curried(1)(_, 3)(2); + * // => [1, 2, 3] */ - function flatten(array, isShallow, callback, thisArg) { - // juggle arguments - if (typeof isShallow != 'boolean' && isShallow != null) { - thisArg = callback; - callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow; - isShallow = false; + function curry(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = null; } - if (callback != null) { - array = map(array, callback, thisArg); - } - return baseFlatten(array, isShallow); + var result = createWrapper(func, CURRY_FLAG, null, null, null, null, null, arity); + result.placeholder = curry.placeholder; + return result; } /** - * Gets the index at which the first occurrence of `value` is found using - * strict equality for comparisons, i.e. `===`. If the array is already sorted - * providing `true` for `fromIndex` will run a faster binary search. + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method does not set the `length` property of curried functions. + * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {boolean|number} [fromIndex=0] The index to search from or `true` - * to perform a binary search on a sorted array. - * @returns {number} Returns the index of the matched value or `-1`. + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Function} Returns the new curried function. * @example * - * _.indexOf([1, 2, 3, 1, 2, 3], 2); - * // => 1 + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; * - * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); - * // => 4 + * var curried = _.curryRight(abc); * - * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); - * // => 2 + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // using placeholders + * curried(3)(1, _)(2); + * // => [1, 2, 3] */ - function indexOf(array, value, fromIndex) { - if (typeof fromIndex == 'number') { - var length = array ? array.length : 0; - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0); - } else if (fromIndex) { - var index = sortedIndex(array, value); - return array[index] === value ? index : -1; + function curryRight(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = null; } - return baseIndexOf(array, value, fromIndex); + var result = createWrapper(func, CURRY_RIGHT_FLAG, null, null, null, null, null, arity); + result.placeholder = curryRight.placeholder; + return result; } /** - * Gets all but the last element or last `n` elements of an array. If a - * callback is provided elements at the end of the array are excluded from - * the result as long as the callback returns truey. The callback is bound - * to `thisArg` and invoked with three arguments; (value, index, array). + * Creates a function that delays invoking `func` until after `wait` milliseconds + * have elapsed since the last time it was invoked. The created function comes + * with a `cancel` method to cancel delayed invocations. Provide an options + * object to indicate that `func` should be invoked on the leading and/or + * trailing edge of the `wait` timeout. Subsequent calls to the debounced + * function return the result of the last `func` invocation. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked + * on the trailing edge of the timeout only if the the debounced function is + * invoked more than once during the `wait` timeout. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) + * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @category Function + * @param {Function} func The function to debounce. + * @param {number} wait The number of milliseconds to delay. + * @param {Object} [options] The options object. + * @param {boolean} [options.leading=false] Specify invoking on the leading + * edge of the timeout. + * @param {number} [options.maxWait] The maximum time `func` is allowed to be + * delayed before it is invoked. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing + * edge of the timeout. + * @returns {Function} Returns the new debounced function. * @example * - * _.initial([1, 2, 3]); - * // => [1, 2] + * // avoid costly calculations while the window size is in flux + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * - * _.initial([1, 2, 3], 2); - * // => [1] + * // invoke `sendMail` when the click event is fired, debouncing subsequent calls + * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); * - * _.initial([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [1] + * // ensure `batchLog` is invoked once after 1 second of debounced calls + * var source = new EventSource('/stream'); + * jQuery(source).on('message', _.debounce(batchLog, 250, { + * 'maxWait': 1000 + * })); * - * var characters = [ - * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * // cancel a debounced call + * var todoChanges = _.debounce(batchLog, 1000); + * Object.observe(models.todo, todoChanges); * - * // using "_.pluck" callback shorthand - * _.initial(characters, 'blocked'); - * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }] + * Object.observe(models, function(changes) { + * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { + * todoChanges.cancel(); + * } + * }, ['delete']); * - * // using "_.where" callback shorthand - * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); - * // => ['barney', 'fred'] + * // ...at some point `models.todo` is changed + * models.todo.completed = true; + * + * // ...before 1 second has passed `models.todo` is deleted + * // which cancels the debounced `todoChanges` call + * delete models.todo; */ - function initial(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; + function debounce(func, wait, options) { + var args, + maxTimeoutId, + result, + stamp, + thisArg, + timeoutId, + trailingCall, + lastCalled = 0, + maxWait = false, + trailing = true; - if (typeof callback != 'number' && callback != null) { - var index = length; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { - n++; + if (!isFunction(func)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : wait; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = options.leading; + maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); + trailing = 'trailing' in options ? options.trailing : trailing; + } + + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); } - } else { - n = (callback == null || thisArg) ? 1 : callback || n; + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; } - return slice(array, 0, nativeMin(nativeMax(0, length - n), length)); - } - /** - * Creates an array of unique values present in all provided arrays using - * strict equality for comparisons, i.e. `===`. - * - * @static - * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of shared values. - * @example - * - * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); - * // => [1, 2] - */ - function intersection() { - var args = [], - argsIndex = -1, - argsLength = arguments.length, - caches = getArray(), - indexOf = getIndexOf(), - trustIndexOf = indexOf === baseIndexOf, - seen = getArray(); + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + var isCalled = trailingCall; + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + } + } else { + timeoutId = setTimeout(delayed, remaining); + } + } - while (++argsIndex < argsLength) { - var value = arguments[argsIndex]; - if (isArray(value) || isArguments(value)) { - args.push(value); - caches.push(trustIndexOf && value.length >= largeArraySize && - createCache(argsIndex ? args[argsIndex] : seen)); + function maxDelayed() { + if (timeoutId) { + clearTimeout(timeoutId); } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (trailing || (maxWait !== wait)) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + } } - var array = args[0], - index = -1, - length = array ? array.length : 0, - result = []; - outer: - while (++index < length) { - var cache = caches[0]; - value = array[index]; + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); - if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) { - argsIndex = argsLength; - (cache || seen).push(value); - while (--argsIndex) { - cache = caches[argsIndex]; - if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { - continue outer; + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), + isCalled = remaining <= 0 || remaining > maxWait; + + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); } + lastCalled = stamp; + result = func.apply(thisArg, args); } - result.push(value); + else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } } - } - while (argsLength--) { - cache = caches[argsLength]; - if (cache) { - releaseObject(cache); + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); } + else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + return result; } - releaseArray(caches); - releaseArray(seen); - return result; + debounced.cancel = cancel; + return debounced; } /** - * Gets the last element or last `n` elements of an array. If a callback is - * provided elements at the end of the array are returned as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it is invoked. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke the function with. + * @returns {number} Returns the timer id. + * @example * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * _.defer(function(text) { console.log(text); }, 'deferred'); + * // logs 'deferred' after one or more milliseconds + */ + function defer(func) { + return baseDelay(func, 1, arguments, 1); + } + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it is invoked. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the last element(s) of `array`. + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke the function with. + * @returns {number} Returns the timer id. * @example * - * _.last([1, 2, 3]); - * // => 3 + * _.delay(function(text) { console.log(text); }, 1000, 'later'); + * // => logs 'later' after one second + */ + function delay(func, wait) { + return baseDelay(func, wait, arguments, 2); + } + + /** + * Creates a function that returns the result of invoking the provided + * functions with the `this` binding of the created function, where each + * successive invocation is supplied the return value of the previous. * - * _.last([1, 2, 3], 2); - * // => [2, 3] + * @static + * @memberOf _ + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example * - * _.last([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [2, 3] + * function add(x, y) { + * return x + y; + * } * - * var characters = [ - * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * function square(n) { + * return n * n; + * } * - * // using "_.pluck" callback shorthand - * _.pluck(_.last(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.last(characters, { 'employer': 'na' }); - * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] + * var addSquare = _.flow(add, square); + * addSquare(1, 2); + * // => 9 */ - function last(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; + function flow() { + var funcs = arguments, + length = funcs.length; - if (typeof callback != 'number' && callback != null) { - var index = length; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { - n++; - } - } else { - n = callback; - if (n == null || thisArg) { - return array ? array[length - 1] : undefined; - } + if (!length) { + return function() {}; } - return slice(array, nativeMax(0, length - n)); + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = 0, + result = funcs[index].apply(this, arguments); + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; } /** - * Gets the index at which the last occurrence of `value` is found using strict - * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used - * as the offset from the end of the collection. + * This method is like `_.flow` except that it creates a function that + * invokes the provided functions from right to left. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {number} [fromIndex=array.length-1] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. + * @alias backflow, compose + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. * @example * - * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); - * // => 4 + * function add(x, y) { + * return x + y; + * } * - * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); - * // => 1 + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flowRight(square, add); + * addSquare(1, 2); + * // => 9 */ - function lastIndexOf(array, value, fromIndex) { - var index = array ? array.length : 0; - if (typeof fromIndex == 'number') { - index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; + function flowRight() { + var funcs = arguments, + fromIndex = funcs.length - 1; + + if (fromIndex < 0) { + return function() {}; } - while (index--) { - if (array[index] === value) { - return index; - } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); } - return -1; + return function() { + var index = fromIndex, + result = funcs[index].apply(this, arguments); + + while (index--) { + result = funcs[index].call(this, result); + } + return result; + }; } /** - * Removes all provided values from the given array using strict equality for - * comparisons, i.e. `===`. + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is coerced to a string and used as the + * cache key. The `func` is invoked with the `this` binding of the memoized + * function. * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the ES `Map` method interface + * of `get`, `has`, and `set`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * for more details. + * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {...*} [value] The values to remove. - * @returns {Array} Returns `array`. + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoizing function. * @example * - * var array = [1, 2, 3, 1, 2, 3]; - * _.pull(array, 2, 3); - * console.log(array); - * // => [1, 1] + * var upperCase = _.memoize(function(string) { + * return string.toUpperCase(); + * }); + * + * upperCase('fred'); + * // => 'FRED' + * + * // modifying the result cache + * upperCase.cache.set('fred', 'BARNEY'); + * upperCase('fred'); + * // => 'BARNEY' + * + * // replacing `_.memoize.Cache` + * var object = { 'user': 'fred' }; + * var other = { 'user': 'barney' }; + * var identity = _.memoize(_.identity); + * + * identity(object); + * // => { 'user': 'fred' } + * identity(other); + * // => { 'user': 'fred' } + * + * _.memoize.Cache = WeakMap; + * var identity = _.memoize(_.identity); + * + * identity(object); + * // => { 'user': 'fred' } + * identity(other); + * // => { 'user': 'barney' } */ - function pull(array) { - var args = arguments, - argsIndex = 0, - argsLength = args.length, - length = array ? array.length : 0; + function memoize(func, resolver) { + if (!isFunction(func) || (resolver && !isFunction(resolver))) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var cache = memoized.cache, + key = resolver ? resolver.apply(this, arguments) : arguments[0]; - while (++argsIndex < argsLength) { - var index = -1, - value = args[argsIndex]; - while (++index < length) { - if (array[index] === value) { - splice.call(array, index--, 1); - length--; - } + if (cache.has(key)) { + return cache.get(key); } + var result = func.apply(this, arguments); + cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache; + return memoized; + } + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (!isFunction(predicate)) { + throw new TypeError(FUNC_ERROR_TEXT); } - return array; + return function() { + return !predicate.apply(this, arguments); + }; } /** - * Creates an array of numbers (positive and/or negative) progressing from - * `start` up to but not including `end`. If `start` is less than `stop` a - * zero-length range is created unless a negative `step` is specified. + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first call. The `func` is invoked + * with the `this` binding of the created function. * * @static * @memberOf _ - * @category Arrays - * @param {number} [start=0] The start of the range. - * @param {number} end The end of the range. - * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns a new range array. + * @type Function + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. * @example * - * _.range(4); - * // => [0, 1, 2, 3] + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // `initialize` invokes `createApplication` once + */ + function once(func) { + return before(func, 2); + } + + /** + * Creates a function that invokes `func` with `partial` arguments prepended + * to those provided to the new function. This method is like `_.bind` except + * it does **not** alter the `this` binding. * - * _.range(1, 5); - * // => [1, 2, 3, 4] + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. * - * _.range(0, 20, 5); - * // => [0, 5, 10, 15] + * **Note:** This method does not set the `length` property of partially + * applied functions. * - * _.range(0, -4, -1); - * // => [0, -1, -2, -3] + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example * - * _.range(1, 4, 0); - * // => [1, 1, 1] + * var greet = function(greeting, name) { + * return greeting + ' ' + name; + * }; * - * _.range(0); - * // => [] + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // using placeholders + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' */ - function range(start, end, step) { - start = +start || 0; - step = typeof step == 'number' ? step : (+step || 1); + function partial(func) { + var partials = baseSlice(arguments, 1), + holders = replaceHolders(partials, partial.placeholder); - if (end == null) { - end = start; - start = 0; - } - // use `Array(length)` so engines like Chakra and V8 avoid slower modes - // http://youtu.be/XAqIpGU8ZZk#t=17m25s - var index = -1, - length = nativeMax(0, ceil((end - start) / (step || 1))), - result = Array(length); - - while (++index < length) { - result[index] = start; - start += step; - } - return result; + return createWrapper(func, PARTIAL_FLAG, null, partials, holders); } /** - * Removes all elements from an array that the callback returns truey for - * and returns an array of removed elements. The callback is bound to `thisArg` - * and invoked with three arguments; (value, index, array). + * This method is like `_.partial` except that partially applied arguments + * are appended to those provided to the new function. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** This method does not set the `length` property of partially + * applied functions. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of removed elements. + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. * @example * - * var array = [1, 2, 3, 4, 5, 6]; - * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * var greet = function(greeting, name) { + * return greeting + ' ' + name; + * }; * - * console.log(array); - * // => [1, 3, 5] + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' * - * console.log(evens); - * // => [2, 4, 6] + * // using placeholders + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' */ - function remove(array, callback, thisArg) { - var index = -1, - length = array ? array.length : 0, - result = []; + function partialRight(func) { + var partials = baseSlice(arguments, 1), + holders = replaceHolders(partials, partialRight.placeholder); - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length) { - var value = array[index]; - if (callback(value, index, array)) { - result.push(value); - splice.call(array, index--, 1); - length--; - } - } - return result; + return createWrapper(func, PARTIAL_RIGHT_FLAG, null, partials, holders); } /** - * The opposite of `_.initial` this method gets all but the first element or - * first `n` elements of an array. If a callback function is provided elements - * at the beginning of the array are excluded from the result as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). + * Creates a function that invokes `func` with arguments arranged according + * to the specified indexes where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * * @static * @memberOf _ - * @alias drop, tail - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes, + * specified as individual indexes or arrays of indexes. + * @returns {Function} Returns the new function. * @example * - * _.rest([1, 2, 3]); - * // => [2, 3] + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, 2, 0, 1); * - * _.rest([1, 2, 3], 2); - * // => [3] + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] * - * _.rest([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [3] + * var map = _.rearg(_.map, [1, 0]); + * map(function(n) { return n * 3; }, [1, 2, 3]); + * // => [3, 6, 9] + */ + function rearg(func) { + var indexes = baseFlatten(arguments, false, false, 1); + return createWrapper(func, REARG_FLAG, null, null, null, indexes); + } + + /** + * Creates a function that only invokes `func` at most once per every `wait` + * milliseconds. The created function comes with a `cancel` method to cancel + * delayed invocations. Provide an options object to indicate that `func` + * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * Subsequent calls to the throttled function return the result of the last + * `func` call. * - * var characters = [ - * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked + * on the trailing edge of the timeout only if the the throttled function is + * invoked more than once during the `wait` timeout. * - * // using "_.pluck" callback shorthand - * _.pluck(_.rest(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] + * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) + * for details over the differences between `_.throttle` and `_.debounce`. * - * // using "_.where" callback shorthand - * _.rest(characters, { 'employer': 'slate' }); - * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to throttle. + * @param {number} wait The number of milliseconds to throttle invocations to. + * @param {Object} [options] The options object. + * @param {boolean} [options.leading=true] Specify invoking on the leading + * edge of the timeout. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing + * edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // avoid excessively updating the position while scrolling + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) + * jQuery('.interactive').on('click', throttled); + * + * // cancel a trailing throttled call + * jQuery(window).on('popstate', throttled.cancel); */ - function rest(array, callback, thisArg) { - if (typeof callback != 'number' && callback != null) { - var n = 0, - index = -1, - length = array ? array.length : 0; + function throttle(func, wait, options) { + var leading = true, + trailing = true; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { - n++; - } - } else { - n = (callback == null || thisArg) ? 1 : nativeMax(0, callback); + if (!isFunction(func)) { + throw new TypeError(FUNC_ERROR_TEXT); } - return slice(array, n); + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + debounceOptions.leading = leading; + debounceOptions.maxWait = +wait; + debounceOptions.trailing = trailing; + return debounce(func, wait, debounceOptions); } /** - * Uses a binary search to determine the smallest index at which a value - * should be inserted into a given sorted array in order to maintain the sort - * order of the array. If a callback is provided it will be executed for - * `value` and each element of `array` to compute their sort ranking. The - * callback is bound to `thisArg` and invoked with one argument; (value). + * Creates a function that provides `value` to the wrapper function as its + * first argument. Any additional arguments provided to the function are + * appended to those provided to the wrapper function. The wrapper is invoked + * with the `this` binding of the created function. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * @static + * @memberOf _ + * @category Function + * @param {*} value The value to wrap. + * @param {Function} wrapper The wrapper function. + * @returns {Function} Returns the new function. + * @example * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * var p = _.wrap(_.escape, function(func, text) { + * return '<p>' + func(text) + '</p>'; + * }); * + * p('fred, barney, & pebbles'); + * // => '<p>fred, barney, &amp; pebbles</p>' + */ + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, + * otherwise they are assigned by reference. If `customizer` is provided it is + * invoked to produce the cloned values. If `customizer` returns `undefined` + * cloning is handled by the method instead. The `customizer` is bound to + * `thisArg` and invoked with two argument; (value [, index|key, object]). + * + * **Note:** This method is loosely based on the structured clone algorithm. + * The enumerable properties of `arguments` objects and objects created by + * constructors other than `Object` are cloned to plain `Object` objects. An + * empty object is returned for uncloneable values such as functions, DOM nodes, + * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) + * for more details. + * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to inspect. - * @param {*} value The value to evaluate. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. + * @category Lang + * @param {*} value The value to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {*} Returns the cloned value. * @example * - * _.sortedIndex([20, 30, 50], 40); - * // => 2 + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; * - * // using "_.pluck" callback shorthand - * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); - * // => 2 + * var shallow = _.clone(users); + * shallow[0] === users[0]; + * // => true * - * var dict = { - * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } - * }; + * var deep = _.clone(users, true); + * deep[0] === users[0]; + * // => false * - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { - * return dict.wordToNumber[word]; + * // using a customizer callback + * var body = _.clone(document.body, function(value) { + * return _.isElement(value) ? value.cloneNode(false) : undefined; * }); - * // => 2 * - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { - * return this.wordToNumber[word]; - * }, dict); - * // => 2 + * body === document.body + * // => false + * body.nodeName + * // => BODY + * body.childNodes.length; + * // => 0 */ - function sortedIndex(array, value, callback, thisArg) { - var low = 0, - high = array ? array.length : low; - - // explicitly reference `identity` for better inlining in Firefox - callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity; - value = callback(value); - - while (low < high) { - var mid = (low + high) >>> 1; - (callback(array[mid]) < value) - ? low = mid + 1 - : high = mid; + function clone(value, isDeep, customizer, thisArg) { + // Juggle arguments. + if (typeof isDeep != 'boolean' && isDeep != null) { + thisArg = customizer; + customizer = isIterateeCall(value, isDeep, thisArg) ? null : isDeep; + isDeep = false; } - return low; + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); + return baseClone(value, isDeep, customizer); } /** - * Creates an array of unique values, in order, of the provided arrays using - * strict equality for comparisons, i.e. `===`. + * Creates a deep clone of `value`. If `customizer` is provided it is invoked + * to produce the cloned values. If `customizer` returns `undefined` cloning + * is handled by the method instead. The `customizer` is bound to `thisArg` + * and invoked with two argument; (value [, index|key, object]). * + * **Note:** This method is loosely based on the structured clone algorithm. + * The enumerable properties of `arguments` objects and objects created by + * constructors other than `Object` are cloned to plain `Object` objects. An + * empty object is returned for uncloneable values such as functions, DOM nodes, + * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) + * for more details. + * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of combined values. + * @category Lang + * @param {*} value The value to deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {*} Returns the deep cloned value. * @example * - * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); - * // => [1, 2, 3, 5, 4] + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * var deep = _.cloneDeep(users); + * deep[0] === users[0]; + * // => false + * + * // using a customizer callback + * var el = _.cloneDeep(document.body, function(value) { + * return _.isElement(value) ? value.cloneNode(true) : undefined; + * }); + * + * body === document.body + * // => false + * body.nodeName + * // => BODY + * body.childNodes.length; + * // => 20 */ - function union() { - return baseUniq(baseFlatten(arguments, true, true)); + function cloneDeep(value, customizer, thisArg) { + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); + return baseClone(value, true, customizer); } /** - * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing - * `true` for `isSorted` will use a faster algorithm. If a callback is provided - * each element of `array` is passed through the callback before uniqueness - * is computed. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). + * Checks if `value` is classified as an `arguments` object. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * * @static * @memberOf _ - * @alias unique - * @category Arrays - * @param {Array} array The array to process. - * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a duplicate-value-free array. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.uniq([1, 2, 1, 3, 1]); - * // => [1, 2, 3] + * (function() { return _.isArguments(arguments); })(); + * // => true * - * _.uniq([1, 1, 2, 2, 3], true); - * // => [1, 2, 3] + * _.isArguments([1, 2, 3]); + * // => false + */ + function isArguments(value) { + var length = isObjectLike(value) ? value.length : undefined; + return (isLength(length) && objToString.call(value) == argsTag) || false; + } + // Fallback for environments without a `toStringTag` for `arguments` objects. + if (!support.argsTag) { + isArguments = function(value) { + var length = isObjectLike(value) ? value.length : undefined; + return (isLength(length) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee')) || false; + }; + } + + /** + * Checks if `value` is classified as an `Array` object. * - * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); - * // => ['A', 'b', 'C'] + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example * - * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); - * // => [1, 2.5, 3] + * _.isArray([1, 2, 3]); + * // => true * - * // using "_.pluck" callback shorthand - * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }, { 'x': 2 }] + * (function() { return _.isArray(arguments); })(); + * // => false */ - function uniq(array, isSorted, callback, thisArg) { - // juggle arguments - if (typeof isSorted != 'boolean' && isSorted != null) { - thisArg = callback; - callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted; - isSorted = false; - } - if (callback != null) { - callback = lodash.createCallback(callback, thisArg, 3); - } - return baseUniq(array, isSorted, callback); - } + var isArray = nativeIsArray || function(value) { + return (isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag) || false; + }; /** - * Creates an array excluding all provided values using strict equality for - * comparisons, i.e. `===`. + * Checks if `value` is classified as a boolean primitive or object. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to filter. - * @param {...*} [value] The values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); - * // => [2, 3, 4] + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false */ - function without(array) { - return baseDifference(array, slice(arguments, 1)); + function isBoolean(value) { + return (value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag) || false; } /** - * Creates an array that is the symmetric difference of the provided arrays. - * See http://en.wikipedia.org/wiki/Symmetric_difference. + * Checks if `value` is classified as a `Date` object. * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of values. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.xor([1, 2, 3], [5, 2, 1, 4]); - * // => [3, 5, 4] + * _.isDate(new Date); + * // => true * - * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); - * // => [1, 4, 5] + * _.isDate('Mon April 23 2012'); + * // => false */ - function xor() { - var index = -1, - length = arguments.length; - - while (++index < length) { - var array = arguments[index]; - if (isArray(array) || isArguments(array)) { - var result = result - ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result))) - : array; - } - } - return result || []; + function isDate(value) { + return (isObjectLike(value) && objToString.call(value) == dateTag) || false; } /** - * Creates an array of grouped elements, the first of which contains the first - * elements of the given arrays, the second of which contains the second - * elements of the given arrays, and so on. + * Checks if `value` is a DOM element. * * @static * @memberOf _ - * @alias unzip - * @category Arrays - * @param {...Array} [array] Arrays to process. - * @returns {Array} Returns a new array of grouped elements. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * - * _.zip(['fred', 'barney'], [30, 40], [true, false]); - * // => [['fred', 30, true], ['barney', 40, false]] + * _.isElement(document.body); + * // => true + * + * _.isElement('<body>'); + * // => false */ - function zip() { - var array = arguments.length > 1 ? arguments : arguments[0], - index = -1, - length = array ? max(pluck(array, 'length')) : 0, - result = Array(length < 0 ? 0 : length); - - while (++index < length) { - result[index] = pluck(array, index); - } - return result; + function isElement(value) { + return (value && value.nodeType === 1 && isObjectLike(value) && + (lodash.support.nodeTag ? objToString.call(value).indexOf('Element') > -1 : isHostObject(value))) || false; } + // Fallback for environments without DOM support. + if (!support.dom) { + isElement = function(value) { + return (value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value)) || false; + }; + } /** - * Creates an object composed from arrays of `keys` and `values`. Provide - * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` - * or two arrays, one of `keys` and one of corresponding `values`. + * Checks if a value is empty. A value is considered empty unless it is an + * `arguments` object, array, string, or jQuery-like collection with a length + * greater than `0` or an object with own enumerable properties. * * @static * @memberOf _ - * @alias object - * @category Arrays - * @param {Array} keys The array of keys. - * @param {Array} [values=[]] The array of values. - * @returns {Object} Returns an object composed of the given keys and - * corresponding values. + * @category Lang + * @param {Array|Object|string} value The value to inspect. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * - * _.zipObject(['fred', 'barney'], [30, 40]); - * // => { 'fred': 30, 'barney': 40 } + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false */ - function zipObject(keys, values) { - var index = -1, - length = keys ? keys.length : 0, - result = {}; - - if (!values && length && !isArray(keys[0])) { - values = []; + function isEmpty(value) { + if (value == null) { + return true; } - while (++index < length) { - var key = keys[index]; - if (values) { - result[key] = values[index]; - } else if (key) { - result[key[0]] = key[1]; - } + var length = value.length; + if (isLength(length) && (isArray(value) || isString(value) || isArguments(value) || + (isObjectLike(value) && isFunction(value.splice)))) { + return !length; } - return result; + return !keys(value).length; } - /*--------------------------------------------------------------------------*/ - /** - * Creates a function that executes `func`, with the `this` binding and - * arguments of the created function, only after being called `n` times. + * Performs a deep comparison between two values to determine if they are + * equivalent. If `customizer` is provided it is invoked to compare values. + * If `customizer` returns `undefined` comparisons are handled by the method + * instead. The `customizer` is bound to `thisArg` and invoked with three + * arguments; (value, other [, index|key]). * + * **Note:** This method supports comparing arrays, booleans, `Date` objects, + * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes + * are **not** supported. Provide a customizer function to extend support + * for comparing other values. + * * @static * @memberOf _ - * @category Functions - * @param {number} n The number of times the function must be called before - * `func` is executed. - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparing values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * - * var saves = ['profile', 'settings']; + * var object = { 'user': 'fred' }; + * var other = { 'user': 'fred' }; * - * var done = _.after(saves.length, function() { - * console.log('Done saving!'); - * }); + * object == other; + * // => false * - * _.forEach(saves, function(type) { - * asyncSave({ 'type': type, 'complete': done }); + * _.isEqual(object, other); + * // => true + * + * // using a customizer callback + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqual(array, other, function(value, other) { + * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined; * }); - * // => logs 'Done saving!', after all saves have completed + * // => true */ - function after(n, func) { - if (!isFunction(func)) { - throw new TypeError; + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); + if (!customizer && isStrictComparable(value) && isStrictComparable(other)) { + return value === other; } - return function() { - if (--n < 1) { - return func.apply(this, arguments); - } - }; + var result = customizer ? customizer(value, other) : undefined; + return typeof result == 'undefined' ? baseIsEqual(value, other, customizer) : !!result; } /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. * @example * - * var func = function(greeting) { - * return greeting + ' ' + this.name; - * }; + * _.isError(new Error); + * // => true * - * func = _.bind(func, { 'name': 'fred' }, 'hi'); - * func(); - * // => 'hi fred' + * _.isError(Error); + * // => false */ - function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) - : createWrapper(func, 1, null, null, thisArg); + function isError(value) { + return (isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag) || false; } /** - * Binds methods of an object to the object itself, overwriting the existing - * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all the function properties - * of `object` will be bound. + * Checks if `value` is a finite primitive number. * + * **Note:** This method is based on ES `Number.isFinite`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) + * for more details. + * * @static * @memberOf _ - * @category Functions - * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. - * @returns {Object} Returns `object`. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * - * var view = { - * 'label': 'docs', - * 'onClick': function() { console.log('clicked ' + this.label); } - * }; + * _.isFinite(10); + * // => true * - * _.bindAll(view); - * jQuery('#docs').on('click', view.onClick); - * // => logs 'clicked docs', when the button is clicked + * _.isFinite('10'); + * // => false + * + * _.isFinite(true); + * // => false + * + * _.isFinite(Object(10)); + * // => false + * + * _.isFinite(Infinity); + * // => false */ - function bindAll(object) { - var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object), - index = -1, - length = funcs.length; + var isFinite = nativeNumIsFinite || function(value) { + return typeof value == 'number' && nativeIsFinite(value); + }; - while (++index < length) { - var key = funcs[index]; - object[key] = createWrapper(object[key], 1, null, null, object); - } - return object; + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + // Avoid a Chakra JIT bug in compatibility modes of IE 11. + // See https://github.com/jashkenas/underscore/issues/1621 for more details. + return typeof value == 'function' || false; } + // Fallback for environments that return incorrect `typeof` operator results. + if (isFunction(/x/) || (Uint8Array && !isFunction(Uint8Array))) { + isFunction = function(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in older versions of Chrome and Safari which return 'function' for regexes + // and Safari 8 equivalents which return 'object' for typed array constructors. + return objToString.call(value) == funcTag; + }; + } /** - * Creates a function that, when called, invokes the method at `object[key]` - * and prepends any additional `bindKey` arguments to those provided to the bound - * function. This method differs from `_.bind` by allowing bound functions to - * reference methods that will be redefined or don't yet exist. - * See http://michaux.ca/articles/lazy-function-definition-pattern. + * Checks if `value` is the language type of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * + * **Note:** See the [ES5 spec](https://es5.github.io/#x8) for more details. + * * @static * @memberOf _ - * @category Functions - * @param {Object} object The object the method belongs to. - * @param {string} key The key of the method. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * - * var object = { - * 'name': 'fred', - * 'greet': function(greeting) { - * return greeting + ' ' + this.name; - * } - * }; + * _.isObject({}); + * // => true * - * var func = _.bindKey(object, 'greet', 'hi'); - * func(); - * // => 'hi fred' + * _.isObject([1, 2, 3]); + * // => true * - * object.greet = function(greeting) { - * return greeting + 'ya ' + this.name + '!'; - * }; - * - * func(); - * // => 'hiya fred!' + * _.isObject(1); + * // => false */ - function bindKey(object, key) { - return arguments.length > 2 - ? createWrapper(key, 19, slice(arguments, 2), null, object) - : createWrapper(key, 3, null, null, object); + function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return type == 'function' || (value && type == 'object') || false; } /** - * Creates a function that is the composition of the provided functions, - * where each function consumes the return value of the function that follows. - * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. - * Each function is executed with the `this` binding of the composed function. + * Performs a deep comparison between `object` and `source` to determine if + * `object` contains equivalent property values. If `customizer` is provided + * it is invoked to compare values. If `customizer` returns `undefined` + * comparisons are handled by the method instead. The `customizer` is bound + * to `thisArg` and invoked with three arguments; (value, other, index|key). * + * **Note:** This method supports comparing properties of arrays, booleans, + * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions + * and DOM nodes are **not** supported. Provide a customizer function to extend + * support for comparing other values. + * * @static * @memberOf _ - * @category Functions - * @param {...Function} [func] Functions to compose. - * @returns {Function} Returns the new composed function. + * @category Lang + * @param {Object} source The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparing values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. * @example * - * var realNameMap = { - * 'pebbles': 'penelope' - * }; + * var object = { 'user': 'fred', 'age': 40 }; * - * var format = function(name) { - * name = realNameMap[name.toLowerCase()] || name; - * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - * }; + * _.isMatch(object, { 'age': 40 }); + * // => true * - * var greet = function(formatted) { - * return 'Hiya ' + formatted + '!'; - * }; + * _.isMatch(object, { 'age': 36 }); + * // => false * - * var welcome = _.compose(greet, format); - * welcome('pebbles'); - * // => 'Hiya Penelope!' + * // using a customizer callback + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatch(object, source, function(value, other) { + * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined; + * }); + * // => true */ - function compose() { - var funcs = arguments, - length = funcs.length; + function isMatch(object, source, customizer, thisArg) { + var props = keys(source), + length = props.length; - while (length--) { - if (!isFunction(funcs[length])) { - throw new TypeError; + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); + if (!customizer && length == 1) { + var key = props[0], + value = source[key]; + + if (isStrictComparable(value)) { + return object != null && value === object[key] && hasOwnProperty.call(object, key); } } - return function() { - var args = arguments, - length = funcs.length; + var values = Array(length), + strictCompareFlags = Array(length); - while (length--) { - args = [funcs[length].apply(this, args)]; - } - return args[0]; - }; + while (length--) { + value = values[length] = source[props[length]]; + strictCompareFlags[length] = isStrictComparable(value); + } + return baseIsMatch(object, props, values, strictCompareFlags, customizer); } /** - * Creates a function which accepts one or more arguments of `func` that when - * invoked either executes `func` returning its result, if all `func` arguments - * have been provided, or returns a function that accepts one or more of the - * remaining `func` arguments, and so on. The arity of `func` can be specified - * if `func.length` is not sufficient. + * Checks if `value` is `NaN`. * + * **Note:** This method is not the same as native `isNaN` which returns `true` + * for `undefined` and other non-numeric values. See the [ES5 spec](https://es5.github.io/#x15.1.2.4) + * for more details. + * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to curry. - * @param {number} [arity=func.length] The arity of `func`. - * @returns {Function} Returns the new curried function. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. * @example * - * var curried = _.curry(function(a, b, c) { - * console.log(a + b + c); - * }); + * _.isNaN(NaN); + * // => true * - * curried(1)(2)(3); - * // => 6 + * _.isNaN(new Number(NaN)); + * // => true * - * curried(1, 2)(3); - * // => 6 + * isNaN(undefined); + * // => true * - * curried(1, 2, 3); - * // => 6 + * _.isNaN(undefined); + * // => false */ - function curry(func, arity) { - arity = typeof arity == 'number' ? arity : (+arity || func.length); - return createWrapper(func, 4, null, null, null, arity); + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some host objects in IE. + return isNumber(value) && value != +value; } /** - * Creates a function that will delay the execution of `func` until after - * `wait` milliseconds have elapsed since the last time it was invoked. - * Provide an options object to indicate that `func` should be invoked on - * the leading and/or trailing edge of the `wait` timeout. Subsequent calls - * to the debounced function will return the result of the last `func` call. + * Checks if `value` is a native function. * - * Note: If `leading` and `trailing` options are `true` `func` will be called - * on the trailing edge of the timeout only if the the debounced function is - * invoked more than once during the `wait` timeout. + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @example * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (value == null) { + return false; + } + if (objToString.call(value) == funcTag) { + return reNative.test(fnToString.call(value)); + } + return (isObjectLike(value) && + (isHostObject(value) ? reNative : reHostCtor).test(value)) || false; + } + + /** + * Checks if `value` is `null`. + * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to debounce. - * @param {number} wait The number of milliseconds to delay. - * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout. - * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. - * @returns {Function} Returns the new debounced function. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. * @example * - * // avoid costly calculations while the window size is in flux - * var lazyLayout = _.debounce(calculateLayout, 150); - * jQuery(window).on('resize', lazyLayout); + * _.isNull(null); + * // => true * - * // execute `sendMail` when the click event is fired, debouncing subsequent calls - * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * }); + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. * - * // ensure `batchLog` is executed once after 1 second of debounced calls - * var source = new EventSource('/stream'); - * source.addEventListener('message', _.debounce(batchLog, 250, { - * 'maxWait': 1000 - * }, false); + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified + * as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isNumber(8.4); + * // => true + * + * _.isNumber(NaN); + * // => true + * + * _.isNumber('8.4'); + * // => false */ - function debounce(func, wait, options) { - var args, - maxTimeoutId, - result, - stamp, - thisArg, - timeoutId, - trailingCall, - lastCalled = 0, - maxWait = false, - trailing = true; + function isNumber(value) { + return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag) || false; + } - if (!isFunction(func)) { - throw new TypeError; + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * **Note:** This method assumes objects created by the `Object` constructor + * have no inherited enumerable properties. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { + if (!(value && objToString.call(value) == objectTag) || (!lodash.support.argsTag && isArguments(value))) { + return false; } - wait = nativeMax(0, wait) || 0; - if (options === true) { - var leading = true; - trailing = false; - } else if (isObject(options)) { - leading = options.leading; - maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0); - trailing = 'trailing' in options ? options.trailing : trailing; - } - var delayed = function() { - var remaining = wait - (now() - stamp); - if (remaining <= 0) { - if (maxTimeoutId) { - clearTimeout(maxTimeoutId); - } - var isCalled = trailingCall; - maxTimeoutId = timeoutId = trailingCall = undefined; - if (isCalled) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } - } else { - timeoutId = setTimeout(delayed, remaining); - } - }; + var valueOf = value.valueOf, + objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); - var maxDelayed = function() { - if (timeoutId) { - clearTimeout(timeoutId); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if (trailing || (maxWait !== wait)) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } - }; + return objProto + ? (value == objProto || getPrototypeOf(value) == objProto) + : shimIsPlainObject(value); + }; - return function() { - args = arguments; - stamp = now(); - thisArg = this; - trailingCall = trailing && (timeoutId || !leading); + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + function isRegExp(value) { + return (isObject(value) && objToString.call(value) == regexpTag) || false; + } - if (maxWait === false) { - var leadingCall = leading && !timeoutId; - } else { - if (!maxTimeoutId && !leading) { - lastCalled = stamp; - } - var remaining = maxWait - (stamp - lastCalled), - isCalled = remaining <= 0; + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag) || false; + } - if (isCalled) { - if (maxTimeoutId) { - maxTimeoutId = clearTimeout(maxTimeoutId); - } - lastCalled = stamp; - result = func.apply(thisArg, args); - } - else if (!maxTimeoutId) { - maxTimeoutId = setTimeout(maxDelayed, remaining); - } - } - if (isCalled && timeoutId) { - timeoutId = clearTimeout(timeoutId); - } - else if (!timeoutId && wait !== maxWait) { - timeoutId = setTimeout(delayed, wait); - } - if (leadingCall) { - isCalled = true; - result = func.apply(thisArg, args); - } - if (isCalled && !timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - return result; - }; + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + function isTypedArray(value) { + return (isObjectLike(value) && isLength(value.length) && typedArrayTags[objToString.call(value)]) || false; } /** - * Defers executing the `func` function until the current call stack has cleared. - * Additional arguments will be provided to `func` when it is invoked. + * Checks if `value` is `undefined`. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to defer. - * @param {...*} [arg] Arguments to invoke the function with. - * @returns {number} Returns the timer id. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. * @example * - * _.defer(function(text) { console.log(text); }, 'deferred'); - * // logs 'deferred' after one or more milliseconds + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false */ - function defer(func) { - if (!isFunction(func)) { - throw new TypeError; - } - var args = slice(arguments, 1); - return setTimeout(function() { func.apply(undefined, args); }, 1); + function isUndefined(value) { + return typeof value == 'undefined'; } /** - * Executes the `func` function after `wait` milliseconds. Additional arguments - * will be provided to `func` when it is invoked. + * Converts `value` to an array. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay execution. - * @param {...*} [arg] Arguments to invoke the function with. - * @returns {number} Returns the timer id. + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. * @example * - * _.delay(function(text) { console.log(text); }, 1000, 'later'); - * // => logs 'later' after one second + * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3); + * // => [2, 3] */ - function delay(func, wait) { - if (!isFunction(func)) { - throw new TypeError; + function toArray(value) { + var length = value ? value.length : 0; + if (!isLength(length)) { + return values(value); } - var args = slice(arguments, 2); - return setTimeout(function() { func.apply(undefined, args); }, wait); + if (!length) { + return []; + } + return (lodash.support.unindexedChars && isString(value)) + ? value.split('') + : arrayCopy(value); } /** - * Creates a function that memoizes the result of `func`. If `resolver` is - * provided it will be used to determine the cache key for storing the result - * based on the arguments provided to the memoized function. By default, the - * first argument provided to the memoized function is used as the cache key. - * The `func` is executed with the `this` binding of the memoized function. - * The result cache is exposed as the `cache` property on the memoized function. + * Converts `value` to a plain object flattening inherited enumerable + * properties of `value` to own properties of the plain object. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] A function used to resolve the cache key. - * @returns {Function} Returns the new memoizing function. + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. * @example * - * var fibonacci = _.memoize(function(n) { - * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable properties of source object(s) to the destination + * object. Subsequent sources overwrite property assignments of previous sources. + * If `customizer` is provided it is invoked to produce the assigned values. + * The `customizer` is bound to `thisArg` and invoked with five arguments; + * (objectValue, sourceValue, key, object, source). + * + * @static + * @memberOf _ + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @param {Function} [customizer] The function to customize assigning values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {Object} Returns `object`. + * @example + * + * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' }); + * // => { 'user': 'fred', 'age': 40 } + * + * // using a customizer callback + * var defaults = _.partialRight(_.assign, function(value, other) { + * return typeof value == 'undefined' ? other : value; * }); * - * fibonacci(9) - * // => 34 + * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); + * // => { 'user': 'barney', 'age': 36 } + */ + var assign = createAssigner(baseAssign); + + /** + * Creates an object that inherits from the given `prototype` object. If a + * `properties` object is provided its own enumerable properties are assigned + * to the created object. * - * var data = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; + * @static + * @memberOf _ + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Object} Returns the new object. + * @example * - * // modifying the result cache - * var get = _.memoize(function(name) { return data[name]; }, _.identity); - * get('pebbles'); - * // => { 'name': 'pebbles', 'age': 1 } + * function Shape() { + * this.x = 0; + * this.y = 0; + * } * - * get.cache.pebbles.name = 'penelope'; - * get('pebbles'); - * // => { 'name': 'penelope', 'age': 1 } + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true */ - function memoize(func, resolver) { - if (!isFunction(func)) { - throw new TypeError; + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = null; } - var memoized = function() { - var cache = memoized.cache, - key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0]; - - return hasOwnProperty.call(cache, key) - ? cache[key] - : (cache[key] = func.apply(this, arguments)); - } - memoized.cache = {}; - return memoized; + return properties ? baseCopy(properties, result, keys(properties)) : result; } /** - * Creates a function that is restricted to execute `func` once. Repeat calls to - * the function will return the value of the first call. The `func` is executed - * with the `this` binding of the created function. + * Assigns own enumerable properties of source object(s) to the destination + * object for all destination properties that resolve to `undefined`. Once a + * property is set, additional defaults of the same property are ignored. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. * @example * - * var initialize = _.once(createApplication); - * initialize(); - * initialize(); - * // `initialize` executes `createApplication` once + * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); + * // => { 'user': 'barney', 'age': 36 } */ - function once(func) { - var ran, - result; - - if (!isFunction(func)) { - throw new TypeError; + function defaults(object) { + if (object == null) { + return object; } - return function() { - if (ran) { - return result; - } - ran = true; - result = func.apply(this, arguments); - - // clear the `func` variable so the function may be garbage collected - func = null; - return result; - }; + var args = arrayCopy(arguments); + args.push(assignDefaults); + return assign.apply(undefined, args); } /** - * Creates a function that, when called, invokes `func` with any additional - * `partial` arguments prepended to those provided to the new function. This - * method is similar to `_.bind` except it does **not** alter the `this` binding. + * This method is like `_.findIndex` except that it returns the key of the + * first element `predicate` returns truthy for, instead of the element itself. * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to partially apply arguments to. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new partially applied function. + * @category Object + * @param {Object} object The object to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * - * var greet = function(greeting, name) { return greeting + ' ' + name; }; - * var hi = _.partial(greet, 'hi'); - * hi('fred'); - * // => 'hi fred' + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(chr) { return chr.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // using the "_.matches" callback shorthand + * _.findKey(users, { 'age': 1 }); + * // => 'pebbles' + * + * // using the "_.property" callback shorthand + * _.findKey(users, 'active'); + * // => 'barney' */ - function partial(func) { - return createWrapper(func, 16, slice(arguments, 1)); + function findKey(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, baseForOwn, true); } /** - * This method is like `_.partial` except that `partial` arguments are - * appended to those provided to the new function. + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. * + * If a property name is provided for `predicate` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `predicate` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to partially apply arguments to. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new partially applied function. + * @category Object + * @param {Object} object The object to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * - * var defaultsDeep = _.partialRight(_.merge, _.defaults); - * - * var options = { - * 'variable': 'data', - * 'imports': { 'jq': $ } + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } * }; * - * defaultsDeep(options, _.templateSettings); + * _.findLastKey(users, function(chr) { return chr.age < 40; }); + * // => returns `pebbles` assuming `_.findKey` returns `barney` * - * options.variable - * // => 'data' + * // using the "_.matches" callback shorthand + * _.findLastKey(users, { 'age': 36 }); + * // => 'barney' * - * options.imports - * // => { '_': _, 'jq': $ } + * // using the "_.property" callback shorthand + * _.findLastKey(users, 'active'); + * // => 'pebbles' */ - function partialRight(func) { - return createWrapper(func, 32, null, slice(arguments, 1)); + function findLastKey(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, baseForOwnRight, true); } /** - * Creates a function that, when executed, will only call the `func` function - * at most once per every `wait` milliseconds. Provide an options object to - * indicate that `func` should be invoked on the leading and/or trailing edge - * of the `wait` timeout. Subsequent calls to the throttled function will - * return the result of the last `func` call. + * Iterates over own and inherited enumerable properties of an object invoking + * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked + * with three arguments; (value, key, object). Iterator functions may exit + * iteration early by explicitly returning `false`. * - * Note: If `leading` and `trailing` options are `true` `func` will be called - * on the trailing edge of the timeout only if the the throttled function is - * invoked more than once during the `wait` timeout. + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. + * @example * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed) + */ + function forIn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return baseFor(object, iteratee, keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to throttle. - * @param {number} wait The number of milliseconds to throttle executions to. - * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout. - * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. - * @returns {Function} Returns the new throttled function. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. * @example * - * // avoid excessively updating the position while scrolling - * var throttled = _.throttle(updatePosition, 100); - * jQuery(window).on('scroll', throttled); + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes - * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { - * 'trailing': false - * })); + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c' */ - function throttle(func, wait, options) { - var leading = true, - trailing = true; + function forInRight(object, iteratee, thisArg) { + iteratee = bindCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keysIn); + } - if (!isFunction(func)) { - throw new TypeError; + /** + * Iterates over own enumerable properties of an object invoking `iteratee` + * for each property. The `iteratee` is bound to `thisArg` and invoked with + * three arguments; (value, key, object). Iterator functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. + * @example + * + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { + * console.log(key); + * }); + * // => logs '0', '1', and 'length' (iteration order is not guaranteed) + */ + function forOwn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); } - if (options === false) { - leading = false; - } else if (isObject(options)) { - leading = 'leading' in options ? options.leading : leading; - trailing = 'trailing' in options ? options.trailing : trailing; - } - debounceOptions.leading = leading; - debounceOptions.maxWait = wait; - debounceOptions.trailing = trailing; - - return debounce(func, wait, debounceOptions); + return baseForOwn(object, iteratee); } /** - * Creates a function that provides `value` to the wrapper function as its - * first argument. Additional arguments provided to the function are appended - * to those provided to the wrapper function. The wrapper is executed with - * the `this` binding of the created function. + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. * * @static * @memberOf _ - * @category Functions - * @param {*} value The value to wrap. - * @param {Function} wrapper The wrapper function. - * @returns {Function} Returns the new function. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. * @example * - * var p = _.wrap(_.escape, function(func, text) { - * return '<p>' + func(text) + '</p>'; + * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { + * console.log(key); * }); + * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' + */ + function forOwnRight(object, iteratee, thisArg) { + iteratee = bindCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keys); + } + + /** + * Creates an array of function property names from all enumerable properties, + * own and inherited, of `object`. * - * p('Fred, Wilma, & Pebbles'); - * // => '<p>Fred, Wilma, &amp; Pebbles</p>' + * @static + * @memberOf _ + * @alias methods + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the new array of property names. + * @example + * + * _.functions(_); + * // => ['all', 'any', 'bind', ...] */ - function wrap(value, wrapper) { - return createWrapper(wrapper, 16, [value]); + function functions(object) { + return baseFunctions(object, keysIn(object)); } - /*--------------------------------------------------------------------------*/ - /** - * Creates a function that returns `value`. + * Checks if `key` exists as a direct property of `object` instead of an + * inherited property. * * @static * @memberOf _ - * @category Utilities - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new function. + * @category Object + * @param {Object} object The object to inspect. + * @param {string} key The key to check. + * @returns {boolean} Returns `true` if `key` is a direct property, else `false`. * @example * - * var object = { 'name': 'fred' }; - * var getter = _.constant(object); - * getter() === object; + * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); * // => true */ - function constant(value) { - return function() { - return value; - }; + function has(object, key) { + return object ? hasOwnProperty.call(object, key) : false; } /** - * Produces a callback bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite property + * assignments of previous values unless `multiValue` is `true`. * * @static * @memberOf _ - * @category Utilities - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. + * @category Object + * @param {Object} object The object to invert. + * @param {boolean} [multiValue] Allow multiple values per key. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Object} Returns the new inverted object. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * _.invert({ 'first': 'fred', 'second': 'barney' }); + * // => { 'fred': 'first', 'barney': 'second' } * - * // wrap to create custom callback shorthands - * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) { - * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback); - * return !match ? func(callback, thisArg) : function(object) { - * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; - * }; - * }); + * // without `multiValue` + * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }); + * // => { 'fred': 'third', 'barney': 'second' } * - * _.filter(characters, 'age__gt38'); - * // => [{ 'name': 'fred', 'age': 40 }] + * // with `multiValue` + * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); + * // => { 'fred': ['first', 'third'], 'barney': ['second'] } */ - function createCallback(func, thisArg, argCount) { - var type = typeof func; - if (func == null || type == 'function') { - return baseCreateCallback(func, thisArg, argCount); + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = null; } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func), - key = props[0], - a = func[key]; + var index = -1, + props = keys(object), + length = props.length, + result = {}; - // handle "_.where" style callback shorthands - if (props.length == 1 && a === a && !isObject(a)) { - // fast path the common case of providing an object with a single - // property containing a primitive value - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; + while (++index < length) { + var key = props[index], + value = object[key]; - while (length--) { - if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) { - break; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; } } - return result; - }; + else { + result[value] = key; + } + } + return result; } /** - * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their - * corresponding HTML entities. + * Creates an array of the own enumerable property names of `object`. * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) + * for more details. + * * @static * @memberOf _ - * @category Utilities - * @param {string} string The string to escape. - * @returns {string} Returns the escaped string. + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. * @example * - * _.escape('Fred, Wilma, & Pebbles'); - * // => 'Fred, Wilma, &amp; Pebbles' + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] */ - function escape(string) { - return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); + var keys = !nativeKeys ? shimKeys : function(object) { + if (object) { + var Ctor = object.constructor, + length = object.length; + } + if ((typeof Ctor == 'function' && Ctor.prototype === object) || + (typeof object == 'function' ? lodash.support.enumPrototypes : (length && isLength(length)))) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length, + support = lodash.support; + + length = (length && isLength(length) && + (isArray(object) || (support.nonEnumStrings && isString(object)) || + (support.nonEnumArgs && isArguments(object))) && length) || 0; + + var Ctor = object.constructor, + index = -1, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto, + isProto = proto === object, + result = Array(length), + skipIndexes = length > 0, + skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), + skipProto = support.enumPrototypes && typeof object == 'function'; + + while (++index < length) { + result[index] = (index + ''); + } + // lodash skips the `constructor` property when it infers it is iterating + // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` + // attribute of an existing property and the `constructor` property of a + // prototype defaults to non-enumerable. + for (var key in object) { + if (!(skipProto && key == 'prototype') && + !(skipErrorProps && (key == 'message' || key == 'name')) && + !(skipIndexes && isIndex(key, length)) && + !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + if (support.nonEnumShadows && object !== objectProto) { + var tag = object === stringProto ? stringTag : object === errorProto ? errorTag : objToString.call(object), + nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag]; + + if (tag == objectTag) { + proto = objectProto; + } + length = shadowProps.length; + while (length--) { + key = shadowProps[length]; + var nonEnum = nonEnums[key]; + if (!(isProto && nonEnum) && + (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) { + result.push(key); + } + } + } + return result; } /** - * This method returns the first argument provided to it. + * Creates an object with the same keys as `object` and values generated by + * running each own enumerable property of `object` through `iteratee`. The + * iteratee function is bound to `thisArg` and invoked with three arguments; + * (value, key, object). * + * If a property name is provided for `iteratee` the created "_.property" + * style callback returns the property value of the given element. + * + * If an object is provided for `iteratee` the created "_.matches" style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * * @static * @memberOf _ - * @category Utilities - * @param {*} value Any value. - * @returns {*} Returns `value`. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. If a property name or object is provided it is used to + * create a "_.property" or "_.matches" style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns the new mapped object. * @example * - * var object = { 'name': 'fred' }; - * _.identity(object) === object; - * // => true + * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(n) { return n * 3; }); + * // => { 'a': 3, 'b': 6, 'c': 9 } + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * // using the "_.property" callback shorthand + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) */ - function identity(value) { - return value; + function mapValues(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + + baseForOwn(object, function(value, key, object) { + result[key] = iteratee(value, key, object); + }); + return result; } /** - * Adds function properties of a source object to the destination object. - * If `object` is a function methods will be added to its prototype as well. + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined` into the destination object. Subsequent sources + * overwrite property assignments of previous sources. If `customizer` is + * provided it is invoked to produce the merged values of the destination and + * source properties. If `customizer` returns `undefined` merging is handled + * by the method instead. The `customizer` is bound to `thisArg` and invoked + * with five arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ - * @category Utilities - * @param {Function|Object} [object=lodash] object The destination object. - * @param {Object} source The object of functions to add. - * @param {Object} [options] The options object. - * @param {boolean} [options.chain=true] Specify whether the functions added are chainable. + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @param {Function} [customizer] The function to customize merging properties. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {Object} Returns `object`. * @example * - * function capitalize(string) { - * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); - * } + * var users = { + * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] + * }; * - * _.mixin({ 'capitalize': capitalize }); - * _.capitalize('fred'); - * // => 'Fred' + * var ages = { + * 'data': [{ 'age': 36 }, { 'age': 40 }] + * }; * - * _('fred').capitalize().value(); - * // => 'Fred' + * _.merge(users, ages); + * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } * - * _.mixin({ 'capitalize': capitalize }, { 'chain': false }); - * _('fred').capitalize(); - * // => 'Fred' + * // using a customizer callback + * var object = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var other = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(object, other, function(a, b) { + * return _.isArray(a) ? a.concat(b) : undefined; + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } */ - function mixin(object, source, options) { - var chain = true, - methodNames = source && functions(source); + var merge = createAssigner(baseMerge); - if (!source || (!options && !methodNames.length)) { - if (options == null) { - options = source; - } - ctor = lodashWrapper; - source = object; - object = lodash; - methodNames = functions(source); + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable properties of `object` that are not omitted. + * Property names may be specified as individual arguments or as arrays of + * property names. If `predicate` is provided it is invoked for each property + * of `object` omitting the properties `predicate` returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; + * (value, key, object). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {Function|...(string|string[])} [predicate] The function invoked per + * iteration or property names to omit, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'user': 'fred', 'age': 40 }; + * + * _.omit(object, 'age'); + * // => { 'user': 'fred' } + * + * _.omit(object, _.isNumber); + * // => { 'user': 'fred' } + */ + function omit(object, predicate, thisArg) { + if (object == null) { + return {}; } - if (options === false) { - chain = false; - } else if (isObject(options) && 'chain' in options) { - chain = options.chain; + if (typeof predicate != 'function') { + var props = arrayMap(baseFlatten(arguments, false, false, 1), String); + return pickByArray(object, baseDifference(keysIn(object), props)); } - var ctor = object, - isFunc = isFunction(ctor); + predicate = bindCallback(predicate, thisArg, 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + } - forEach(methodNames, function(methodName) { - var func = object[methodName] = source[methodName]; - if (isFunc) { - ctor.prototype[methodName] = function() { - var chainAll = this.__chain__, - value = this.__wrapped__, - args = [value]; + /** + * Creates a two dimensional array of the key-value pairs for `object`, + * e.g. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the new array of key-value pairs. + * @example + * + * _.pairs({ 'barney': 36, 'fred': 40 }); + * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) + */ + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); - push.apply(args, arguments); - var result = func.apply(object, args); - if (chain || chainAll) { - if (value === result && isObject(result)) { - return this; - } - result = new ctor(result); - result.__chain__ = chainAll; - } - return result; - }; - } - }); + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; + } + return result; } /** - * Reverts the '_' variable to its previous value and returns a reference to - * the `lodash` function. + * Creates an object composed of the picked `object` properties. Property + * names may be specified as individual arguments or as arrays of property + * names. If `predicate` is provided it is invoked for each property of `object` + * picking the properties `predicate` returns truthy for. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, key, object). * * @static * @memberOf _ - * @category Utilities - * @returns {Function} Returns the `lodash` function. + * @category Object + * @param {Object} object The source object. + * @param {Function|...(string|string[])} [predicate] The function invoked per + * iteration or property names to pick, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Object} Returns the new object. * @example * - * var lodash = _.noConflict(); + * var object = { 'user': 'fred', 'age': 40 }; + * + * _.pick(object, 'user'); + * // => { 'user': 'fred' } + * + * _.pick(object, _.isString); + * // => { 'user': 'fred' } */ - function noConflict() { - context._ = oldDash; - return this; + function pick(object, predicate, thisArg) { + if (object == null) { + return {}; + } + return typeof predicate == 'function' + ? pickByCallback(object, bindCallback(predicate, thisArg, 3)) + : pickByArray(object, baseFlatten(arguments, false, false, 1)); } /** - * A no-operation function. + * Resolves the value of property `key` on `object`. If the value of `key` is + * a function it is invoked with the `this` binding of `object` and its result + * is returned, else the property value is returned. If the property value is + * `undefined` the `defaultValue` is used in its place. * * @static * @memberOf _ - * @category Utilities + * @category Object + * @param {Object} object The object to query. + * @param {string} key The key of the property to resolve. + * @param {*} [defaultValue] The value returned if the property value + * resolves to `undefined`. + * @returns {*} Returns the resolved value. * @example * - * var object = { 'name': 'fred' }; - * _.noop(object) === undefined; - * // => true + * var object = { 'user': 'fred', 'age': _.constant(40) }; + * + * _.result(object, 'user'); + * // => 'fred' + * + * _.result(object, 'age'); + * // => 40 + * + * _.result(object, 'status', 'busy'); + * // => 'busy' + * + * _.result(object, 'status', _.constant('busy')); + * // => 'busy' */ - function noop() { - // no operation performed + function result(object, key, defaultValue) { + var value = object == null ? undefined : object[key]; + if (typeof value == 'undefined') { + value = defaultValue; + } + return isFunction(value) ? value.call(object) : value; } /** - * Gets the number of milliseconds that have elapsed since the Unix epoch - * (1 January 1970 00:00:00 UTC). + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own enumerable + * properties through `iteratee`, with each invocation potentially mutating + * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked + * with four arguments; (accumulator, value, key, object). Iterator functions + * may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ - * @category Utilities + * @category Object + * @param {Array|Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {*} Returns the accumulated value. * @example * - * var stamp = _.now(); - * _.defer(function() { console.log(_.now() - stamp); }); - * // => logs the number of milliseconds it took for the deferred function to be called + * var squares = _.transform([1, 2, 3, 4, 5, 6], function(result, n) { + * n *= n; + * if (n % 2) { + * return result.push(n) < 3; + * } + * }); + * // => [1, 9, 25] + * + * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; + * }); + * // => { 'a': 3, 'b': 6, 'c': 9 } */ - var now = isNative(now = Date.now) && now || function() { - return new Date().getTime(); - }; + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor : []; + } else { + accumulator = baseCreate(typeof Ctor == 'function' && Ctor.prototype); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + /** - * Converts the given value into an integer of the specified radix. - * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the - * `value` is a hexadecimal, in which case a `radix` of `16` is used. + * Creates an array of the own enumerable property values of `object`. * - * Note: This method avoids differences in native ES3 and ES5 `parseInt` - * implementations. See http://es5.github.io/#E. + * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ - * @category Utilities - * @param {string} value The value to parse. - * @param {number} [radix] The radix used to interpret the value to parse. - * @returns {number} Returns the new integer value. + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. * @example * - * _.parseInt('08'); - * // => 8 + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] */ - var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) { - // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt` - return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0); - }; + function values(object) { + return baseValues(object, keys(object)); + } /** - * Creates a "_.pluck" style function, which returns the `key` value of a - * given object. + * Creates an array of the own and inherited enumerable property values + * of `object`. * + * **Note:** Non-object values are coerced to objects. + * * @static * @memberOf _ - * @category Utilities - * @param {string} key The name of the property to retrieve. - * @returns {Function} Returns the new function. + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. * @example * - * var characters = [ - * { 'name': 'fred', 'age': 40 }, - * { 'name': 'barney', 'age': 36 } - * ]; + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * var getName = _.property('name'); + * Foo.prototype.c = 3; * - * _.map(characters, getName); - * // => ['barney', 'fred'] - * - * _.sortBy(characters, getName); - * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) */ - function property(key) { - return function(object) { - return object[key]; - }; + function valuesIn(object) { + return baseValues(object, keysIn(object)); } + /*------------------------------------------------------------------------*/ + /** * Produces a random number between `min` and `max` (inclusive). If only one - * argument is provided a number between `0` and the given number will be - * returned. If `floating` is truey or either `min` or `max` are floats a - * floating-point number will be returned instead of an integer. + * argument is provided a number between `0` and the given number is returned. + * If `floating` is `true`, or either `min` or `max` are floats, a floating-point + * number is returned instead of an integer. * * @static * @memberOf _ - * @category Utilities + * @category Number * @param {number} [min=0] The minimum possible value. * @param {number} [max=1] The maximum possible value. - * @param {boolean} [floating=false] Specify returning a floating-point number. - * @returns {number} Returns a random number. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. * @example * * _.random(0, 5); * // => an integer between 0 and 5 * @@ -6415,149 +9235,566 @@ * * _.random(1.2, 5.2); * // => a floating-point number between 1.2 and 5.2 */ function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = null; + } var noMin = min == null, noMax = max == null; if (floating == null) { - if (typeof min == 'boolean' && noMax) { + if (noMax && typeof min == 'boolean') { floating = min; min = 1; } - else if (!noMax && typeof max == 'boolean') { + else if (typeof max == 'boolean') { floating = max; noMax = true; } } if (noMin && noMax) { max = 1; + noMax = false; } min = +min || 0; if (noMax) { max = min; min = 0; } else { max = +max || 0; } if (floating || min % 1 || max % 1) { var rand = nativeRandom(); - return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max); + return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max); } return baseRandom(min, max); } + /*------------------------------------------------------------------------*/ + /** - * Resolves the value of property `key` on `object`. If `key` is a function - * it will be invoked with the `this` binding of `object` and its result returned, - * else the property value is returned. If `object` is falsey then `undefined` - * is returned. + * Converts `string` to camel case. + * See [Wikipedia](https://en.wikipedia.org/wiki/CamelCase) for more details. * * @static * @memberOf _ - * @category Utilities - * @param {Object} object The object to inspect. - * @param {string} key The name of the property to resolve. - * @returns {*} Returns the resolved value. + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. * @example * - * var object = { - * 'cheese': 'crumpets', - * 'stuff': function() { - * return 'nonsense'; - * } - * }; + * _.camelCase('Foo Bar'); + * // => 'fooBar' * - * _.result(object, 'cheese'); - * // => 'crumpets' + * _.camelCase('--foo-bar'); + * // => 'fooBar' * - * _.result(object, 'stuff'); - * // => 'nonsense' + * _.camelCase('__foo_bar__'); + * // => 'fooBar' */ - function result(object, key) { - if (object) { - var value = object[key]; - return isFunction(value) ? object[key]() : value; + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word); + }); + + /** + * Capitalizes the first character of `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('fred'); + * // => 'Fred' + */ + function capitalize(string) { + string = baseToString(string); + return string && (string.charAt(0).toUpperCase() + string.slice(1)); + } + + /** + * Deburrs `string` by converting latin-1 supplementary letters to basic latin letters. + * See [Wikipedia](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * for more details. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to search. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search from. + * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = baseToString(string); + target = (target + ''); + + var length = string.length; + position = (typeof position == 'undefined' ? length : nativeMin(position < 0 ? 0 : (+position || 0), length)) - target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + + /** + * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to + * their corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional characters + * use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't require escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. + * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * Backticks are escaped because in Internet Explorer < 9, they can break out + * of attribute values or HTML comments. See [#102](https://html5sec.org/#102), + * [#108](https://html5sec.org/#108), and [#133](https://html5sec.org/#133) of + * the [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. + * + * When working with HTML you should always quote attribute values to reduce + * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) + * for more details. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, &amp; pebbles' + */ + function escape(string) { + // Reset `lastIndex` because in IE < 9 `String#replace` does not. + string = baseToString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", + * "+", "(", ")", "[", "]", "{" and "}" in `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = baseToString(string); + return (string && reHasRegExpChars.test(string)) + ? string.replace(reRegExpChars, '\\$&') + : string; + } + + /** + * Converts `string` to kebab case (a.k.a. spinal case). + * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles) for + * more details. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__foo_bar__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Pads `string` on the left and right sides if it is shorter then the given + * padding length. The `chars` string may be truncated if the number of padding + * characters can't be evenly divided by the padding length. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; } + var mid = (length - strLength) / 2, + leftLength = floor(mid), + rightLength = ceil(mid); + + chars = createPad('', rightLength, chars); + return chars.slice(0, leftLength) + string + chars; } /** - * A micro-templating method that handles arbitrary delimiters, preserves - * whitespace, and correctly escapes quotes within interpolated code. + * Pads `string` on the left side if it is shorter then the given padding + * length. The `chars` string may be truncated if the number of padding + * characters exceeds the padding length. * - * Note: In the development build, `_.template` utilizes sourceURLs for easier - * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example * - * For more information on precompiling templates see: - * http://lodash.com/custom-builds + * _.padLeft('abc', 6); + * // => ' abc' * - * For more information on Chrome extension sandboxes see: - * http://developer.chrome.com/stable/extensions/sandboxingEval.html + * _.padLeft('abc', 6, '_-'); + * // => '_-_abc' * + * _.padLeft('abc', 3); + * // => 'abc' + */ + function padLeft(string, length, chars) { + string = baseToString(string); + return string && (createPad(string, length, chars) + string); + } + + /** + * Pads `string` on the right side if it is shorter then the given padding + * length. The `chars` string may be truncated if the number of padding + * characters exceeds the padding length. + * * @static * @memberOf _ - * @category Utilities - * @param {string} text The template text. - * @param {Object} data The data object used to populate the text. + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padRight('abc', 6); + * // => 'abc ' + * + * _.padRight('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padRight('abc', 3); + * // => 'abc' + */ + function padRight(string, length, chars) { + string = baseToString(string); + return string && (string + createPad(string, length, chars)); + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, + * in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the ES5 implementation of `parseInt`. + * See the [ES5 spec](https://es5.github.io/#E) for more details. + * + * @static + * @memberOf _ + * @category String + * @param {string} string The string to convert. + * @param {number} [radix] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard && isIterateeCall(string, radix, guard)) { + radix = 0; + } + return nativeParseInt(string, radix); + } + // Fallback for environments with pre-ES5 implementations. + if (nativeParseInt(whitespace + '08') != 8) { + parseInt = function(string, radix, guard) { + // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. + // Chrome fails to trim leading <BOM> whitespace characters. + // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHexPrefix.test(string) ? 16 : 10)); + }; + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=0] The number of times to repeat the string. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n) { + var result = ''; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = floor(n / 2); + string += string; + } while (n); + + return result; + } + + /** + * Converts `string` to snake case. + * See [Wikipedia](https://en.wikipedia.org/wiki/Snake_case) for more details. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--foo-bar'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Converts `string` to start case. + * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage) + * for more details. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__foo_bar__'); + * // => 'Foo Bar' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to search. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : (+position || 0), string.length); + return string.lastIndexOf(target, position) == position; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is provided it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. + * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for more details. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. * @param {Object} [options] The options object. - * @param {RegExp} [options.escape] The "escape" delimiter. + * @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter. - * @param {Object} [options.imports] An object to import into the template as local variables. + * @param {Object} [options.imports] An object to import into the template as free variables. * @param {RegExp} [options.interpolate] The "interpolate" delimiter. - * @param {string} [sourceURL] The sourceURL of the template's compiled source. - * @param {string} [variable] The data object variable name. - * @returns {Function|string} Returns a compiled function when no `data` object - * is given, else it returns the interpolated text. + * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. + * @param {string} [options.variable] The data object variable name. + * @param- {Object} [otherOptions] Enables the legacy `options` param signature. + * @returns {Function} Returns the compiled template function. * @example * * // using the "interpolate" delimiter to create a compiled template - * var compiled = _.template('hello <%= name %>'); - * compiled({ 'name': 'fred' }); - * // => 'hello fred' + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' * - * // using the "escape" delimiter to escape HTML in data property values - * _.template('<b><%- value %></b>', { 'value': '<script>' }); + * // using the HTML "escape" delimiter to escape data property values + * var compiled = _.template('<b><%- value %></b>'); + * compiled({ 'value': '<script>' }); * // => '<b>&lt;script&gt;</b>' * - * // using the "evaluate" delimiter to generate HTML - * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>'; - * _.template(list, { 'people': ['fred', 'barney'] }); + * // using the "evaluate" delimiter to execute JavaScript and generate HTML + * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>'); + * compiled({ 'users': ['fred', 'barney'] }); * // => '<li>fred</li><li>barney</li>' * - * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter - * _.template('hello ${ name }', { 'name': 'pebbles' }); - * // => 'hello pebbles' - * * // using the internal `print` function in "evaluate" delimiters - * _.template('<% print("hello " + name); %>!', { 'name': 'barney' }); + * var compiled = _.template('<% print("hello " + user); %>!'); + * compiled({ 'user': 'barney' }); * // => 'hello barney!' * - * // using a custom template delimiters - * _.templateSettings = { - * 'interpolate': /{{([\s\S]+?)}}/g - * }; + * // using the ES delimiter as an alternative to the default "interpolate" delimiter + * var compiled = _.template('hello ${ user }!'); + * compiled({ 'user': 'pebbles' }); + * // => 'hello pebbles!' * - * _.template('hello {{ name }}!', { 'name': 'mustache' }); + * // using custom template delimiters + * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g; + * var compiled = _.template('hello {{ user }}!'); + * compiled({ 'user': 'mustache' }); * // => 'hello mustache!' * - * // using the `imports` option to import jQuery - * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>'; - * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } }); + * // using backslashes to treat delimiters as plain text + * var compiled = _.template('<%= "\\<%- value %\\>" %>'); + * compiled({ 'value': 'ignored' }); + * // => '<%- value %>' + * + * // using the `imports` option to import `jQuery` as `jq` + * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>'; + * var compiled = _.template(text, { 'imports': { 'jq': jQuery } }); + * compiled({ 'users': ['fred', 'barney'] }); * // => '<li>fred</li><li>barney</li>' * * // using the `sourceURL` option to specify a custom sourceURL for the template - * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' }); + * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' }); * compiled(data); * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector * * // using the `variable` option to ensure a with-statement isn't used in the compiled template - * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' }); + * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' }); * compiled.source; * // => function(data) { - * var __t, __p = '', __e = _.escape; - * __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!'; + * var __t, __p = ''; + * __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!'; * return __p; * } * * // using the `source` property to inline compiled templates for meaningful * // line numbers in error messages and a stack trace @@ -6565,46 +9802,55 @@ * var JST = {\ * "main": ' + _.template(mainText).source + '\ * };\ * '); */ - function template(text, data, options) { - // based on John Resig's `tmpl` implementation - // http://ejohn.org/blog/javascript-micro-templating/ - // and Laura Doktorova's doT.js - // https://github.com/olado/doT + function template(string, options, otherOptions) { + // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/) + // and Laura Doktorova's doT.js (https://github.com/olado/doT). var settings = lodash.templateSettings; - text = String(text || ''); - // avoid missing dependencies when `iteratorTemplate` is not defined - options = defaults({}, options, settings); + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = null; + } + string = baseToString(string); + options = baseAssign(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); - var imports = defaults({}, options.imports, settings.imports), + var imports = baseAssign(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), - importsValues = values(imports); + importsValues = baseValues(imports, importsKeys); - var isEvaluating, + var isEscaping, + isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; - // compile the regexp to match each delimiter + // Compile the regexp to match each delimiter. var reDelimiters = RegExp( (options.escape || reNoMatch).source + '|' + interpolate.source + '|' + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' + (options.evaluate || reNoMatch).source + '|$' , 'g'); - text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + // Use a sourceURL for easier debugging. + var sourceURL = '//# sourceURL=' + + ('sourceURL' in options + ? options.sourceURL + : ('lodash.templateSources[' + (++templateCounter) + ']') + ) + '\n'; + + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { interpolateValue || (interpolateValue = esTemplateValue); - // escape characters that cannot be included in string literals - source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar); + // Escape characters that can't be included in string literals. + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); - // replace delimiters with snippets + // Replace delimiters with snippets. if (escapeValue) { + isEscaping = true; source += "' +\n__e(" + escapeValue + ") +\n'"; } if (evaluateValue) { isEvaluating = true; source += "';\n" + evaluateValue + ";\n__p += '"; @@ -6612,282 +9858,773 @@ if (interpolateValue) { source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; } index = offset + match.length; - // the JS engine embedded in Adobe products requires returning the `match` - // string in order to produce the correct `offset` value + // The JS engine embedded in Adobe products requires returning the `match` + // string in order to produce the correct `offset` value. return match; }); source += "';\n"; - // if `variable` is not specified, wrap a with-statement around the generated - // code to add the data object to the top of the scope chain - var variable = options.variable, - hasVariable = variable; - - if (!hasVariable) { - variable = 'obj'; - source = 'with (' + variable + ') {\n' + source + '\n}\n'; + // If `variable` is not specified wrap a with-statement around the generated + // code to add the data object to the top of the scope chain. + var variable = options.variable; + if (!variable) { + source = 'with (obj) {\n' + source + '\n}\n'; } - // cleanup code by stripping empty strings + // Cleanup code by stripping empty strings. source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) .replace(reEmptyStringMiddle, '$1') .replace(reEmptyStringTrailing, '$1;'); - // frame code as the function body - source = 'function(' + variable + ') {\n' + - (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') + - "var __t, __p = '', __e = _.escape" + + // Frame code as the function body. + source = 'function(' + (variable || 'obj') + ') {\n' + + (variable + ? '' + : 'obj || (obj = {});\n' + ) + + "var __t, __p = ''" + + (isEscaping + ? ', __e = _.escape' + : '' + ) + (isEvaluating ? ', __j = Array.prototype.join;\n' + "function print() { __p += __j.call(arguments, '') }\n" : ';\n' ) + source + 'return __p\n}'; - // Use a sourceURL for easier debugging. - // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl - var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/'; + var result = attempt(function() { + return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues); + }); - try { - var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues); - } catch(e) { - e.source = source; - throw e; - } - if (data) { - return result(data); - } - // provide the compiled function's source by its `toString` method, in - // supported environments, or the `source` property as a convenience for - // inlining compiled templates during the build process + // Provide the compiled function's source by its `toString` method or + // the `source` property as a convenience for inlining compiled templates. result.source = source; + if (isError(result)) { + throw result; + } return result; } /** - * Executes the callback `n` times, returning an array of the results - * of each callback execution. The callback is bound to `thisArg` and invoked - * with one argument; (index). + * Removes leading and trailing whitespace or specified characters from `string`. * * @static * @memberOf _ - * @category Utilities - * @param {number} n The number of times to execute the callback. - * @param {Function} callback The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns an array of the results of each `callback` execution. + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {string} Returns the trimmed string. * @example * - * var diceRolls = _.times(3, _.partial(_.random, 1, 6)); - * // => [3, 6, 4] + * _.trim(' abc '); + * // => 'abc' * - * _.times(3, function(n) { mage.castSpell(n); }); - * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively + * _.trim('-_-abc-_-', '_-'); + * // => 'abc' * - * _.times(3, function(n) { this.cast(n); }, mage); - * // => also calls `mage.castSpell(n)` three times + * _.map([' foo ', ' bar '], _.trim); + * // => ['foo', 'bar] */ - function times(n, callback, thisArg) { - n = (n = +n) > -1 ? n : 0; - var index = -1, - result = Array(n); + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = (chars + ''); + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } - callback = baseCreateCallback(callback, thisArg, 1); - while (++index < n) { - result[index] = callback(index); + /** + * Removes leading whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trimLeft(' abc '); + * // => 'abc ' + * + * _.trimLeft('-_-abc-_-', '_-'); + * // => 'abc-_-' + */ + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; } - return result; + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)) + } + return string.slice(charsLeftIndex(string, (chars + ''))); } /** - * The inverse of `_.escape` this method converts the HTML entities - * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their + * Removes trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trimRight(' abc '); + * // => ' abc' + * + * _.trimRight('-_-abc-_-', '_-'); + * // => '-_-abc' + */ + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1) + } + return string.slice(0, charsRightIndex(string, (chars + '')) + 1); + } + + /** + * Truncates `string` if it is longer than the given maximum string length. + * The last characters of the truncated string are replaced with the omission + * string which defaults to "...". + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to truncate. + * @param {Object|number} [options] The options object or maximum string length. + * @param {number} [options.length=30] The maximum string length. + * @param {string} [options.omission='...'] The string to indicate text is omitted. + * @param {RegExp|string} [options.separator] The separator pattern to truncate to. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {string} Returns the truncated string. + * @example + * + * _.trunc('hi-diddly-ho there, neighborino'); + * // => 'hi-diddly-ho there, neighbo...' + * + * _.trunc('hi-diddly-ho there, neighborino', 24); + * // => 'hi-diddly-ho there, n...' + * + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); + * // => 'hi-diddly-ho there,...' + * + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); + * //=> 'hi-diddly-ho there...' + * + * _.trunc('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); + * // => 'hi-diddly-ho there, neig [...]' + */ + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = null; + } + var length = DEFAULT_TRUNC_LENGTH, + omission = DEFAULT_TRUNC_OMISSION; + + if (options != null) { + if (isObject(options)) { + var separator = 'separator' in options ? options.separator : separator; + length = 'length' in options ? +options.length || 0 : length; + omission = 'omission' in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, + newEnd, + substring = string.slice(0, end); + + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g'); + } + separator.lastIndex = 0; + while ((match = separator.exec(substring))) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + + /** + * The inverse of `_.escape`; this method converts the HTML entities + * `&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#39;`, and `&#96;` in `string` to their * corresponding characters. * + * **Note:** No other HTML entities are unescaped. To unescape additional HTML + * entities use a third-party library like [_he_](https://mths.be/he). + * * @static * @memberOf _ - * @category Utilities - * @param {string} string The string to unescape. + * @category String + * @param {string} [string=''] The string to unescape. * @returns {string} Returns the unescaped string. * @example * - * _.unescape('Fred, Barney &amp; Pebbles'); - * // => 'Fred, Barney & Pebbles' + * _.unescape('fred, barney, &amp; pebbles'); + * // => 'fred, barney, & pebbles' */ function unescape(string) { - return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar); + string = baseToString(string); + return (string && reHasEscapedHtml.test(string)) + ? string.replace(reEscapedHtml, unescapeHtmlChar) + : string; } /** - * Generates a unique ID. If `prefix` is provided the ID will be appended to it. + * Splits `string` into an array of its words. * * @static * @memberOf _ - * @category Utilities - * @param {string} [prefix] The value to prefix the ID with. - * @returns {string} Returns the unique ID. + * @category String + * @param {string} [string=''] The string to inspect. + * @param {RegExp|string} [pattern] The pattern to match words. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the words of `string`. * @example * - * _.uniqueId('contact_'); - * // => 'contact_104' + * _.words('fred, barney, & pebbles'); + * // => ['fred', 'barney', 'pebbles'] * - * _.uniqueId(); - * // => '105' + * _.words('fred, barney, & pebbles', /[^, ]+/g); + * // => ['fred', 'barney', '&', 'pebbles'] */ - function uniqueId(prefix) { - var id = ++idCounter; - return String(prefix == null ? '' : prefix) + id; + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = null; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; } - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** - * Creates a `lodash` object that wraps the given value with explicit - * method chaining enabled. + * Attempts to invoke `func`, returning either the result or the caught + * error object. * * @static * @memberOf _ - * @category Chaining - * @param {*} value The value to wrap. - * @returns {Object} Returns the wrapper object. + * @category Utility + * @param {*} func The function to attempt. + * @returns {*} Returns the `func` result or error object. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 }, - * { 'name': 'pebbles', 'age': 1 } + * // avoid throwing errors for invalid selectors + * var elements = _.attempt(function() { + * return document.querySelectorAll(selector); + * }); + * + * if (_.isError(elements)) { + * elements = []; + * } + */ + function attempt(func) { + try { + return func(); + } catch(e) { + return isError(e) ? e : Error(e); + } + } + + /** + * Creates a function bound to an optional `thisArg`. If `func` is a property + * name the created callback returns the property value for a given element. + * If `func` is an object the created callback returns `true` for elements + * that contain the equivalent object properties, otherwise it returns `false`. + * + * @static + * @memberOf _ + * @alias iteratee + * @category Utility + * @param {*} [func=_.identity] The value to convert to a callback. + * @param {*} [thisArg] The `this` binding of `func`. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Function} Returns the callback. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } * ]; * - * var youngest = _.chain(characters) - * .sortBy('age') - * .map(function(chr) { return chr.name + ' is ' + chr.age; }) - * .first() - * .value(); - * // => 'pebbles is 1' + * // wrap to create custom callback shorthands + * _.callback = _.wrap(_.callback, function(callback, func, thisArg) { + * var match = /^(.+?)__([gl]t)(.+)$/.exec(func); + * if (!match) { + * return callback(func, thisArg); + * } + * return function(object) { + * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; + * }; + * }); + * + * _.filter(users, 'age__gt36'); + * // => [{ 'user': 'fred', 'age': 40 }] */ - function chain(value) { - value = new lodashWrapper(value); - value.__chain__ = true; - return value; + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = null; + } + return isObjectLike(func) + ? matches(func) + : baseCallback(func, thisArg); } /** - * Invokes `interceptor` with the `value` as the first argument and then - * returns `value`. The purpose of this method is to "tap into" a method - * chain in order to perform operations on intermediate results within - * the chain. + * Creates a function that returns `value`. * * @static * @memberOf _ - * @category Chaining - * @param {*} value The value to provide to `interceptor`. - * @param {Function} interceptor The function to invoke. + * @category Utility + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new function. + * @example + * + * var object = { 'user': 'fred' }; + * var getter = _.constant(object); + * getter() === object; + * // => true + */ + function constant(value) { + return function() { + return value; + }; + } + + /** + * This method returns the first argument provided to it. + * + * @static + * @memberOf _ + * @category Utility + * @param {*} value Any value. * @returns {*} Returns `value`. * @example * - * _([1, 2, 3, 4]) - * .tap(function(array) { array.pop(); }) - * .reverse() - * .value(); - * // => [3, 2, 1] + * var object = { 'user': 'fred' }; + * _.identity(object) === object; + * // => true */ - function tap(value, interceptor) { - interceptor(value); + function identity(value) { return value; } /** - * Enables explicit method chaining on the wrapper object. + * Creates a function which performs a deep comparison between a given object + * and `source`, returning `true` if the given object has equivalent property + * values, else `false`. * - * @name chain + * @static * @memberOf _ - * @category Chaining - * @returns {*} Returns the wrapper object. + * @category Utility + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new function. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * var users = [ + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } * ]; * - * // without explicit chaining - * _(characters).first(); - * // => { 'name': 'barney', 'age': 36 } + * var matchesAge = _.matches({ 'age': 36 }); * - * // with explicit chaining - * _(characters).chain() - * .first() - * .pick('age') - * .value(); - * // => { 'age': 36 } + * _.filter(users, matchesAge); + * // => [{ 'user': 'barney', 'age': 36 }] + * + * _.find(users, matchesAge); + * // => { 'user': 'barney', 'age': 36 } */ - function wrapperChain() { - this.__chain__ = true; + function matches(source) { + return baseMatches(baseClone(source, true)); + } + + /** + * Adds all own enumerable function properties of a source object to the + * destination object. If `object` is a function then methods are added to + * its prototype as well. + * + * @static + * @memberOf _ + * @category Utility + * @param {Function|Object} [object=this] object The destination object. + * @param {Object} source The object of functions to add. + * @param {Object} [options] The options object. + * @param {boolean} [options.chain=true] Specify whether the functions added + * are chainable. + * @returns {Function|Object} Returns `object`. + * @example + * + * function vowels(string) { + * return _.filter(string, function(v) { + * return /[aeiou]/i.test(v); + * }); + * } + * + * _.mixin({ 'vowels': vowels }); + * _.vowels('fred'); + * // => ['e'] + * + * _('fred').vowels().value(); + * // => ['e'] + * + * _.mixin({ 'vowels': vowels }, { 'chain': false }); + * _('fred').vowels(); + * // => ['e'] + */ + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), + props = isObj && keys(source), + methodNames = props && props.length && baseFunctions(source, props); + + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, + index = -1, + isFunc = isFunction(object), + length = methodNames.length; + + if (options === false) { + chain = false; + } else if (isObject(options) && 'chain' in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], + func = source[methodName]; + + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = (function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__); + (result.__actions__ = arrayCopy(this.__actions__)).push({ 'func': func, 'args': arguments, 'thisArg': object }); + result.__chain__ = chainAll; + return result; + } + var args = [this.value()]; + push.apply(args, arguments); + return func.apply(object, args); + }; + }(func)); + } + } + return object; + } + + /** + * Reverts the `_` variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @memberOf _ + * @category Utility + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + context._ = oldDash; return this; } /** - * Produces the `toString` result of the wrapped value. + * A no-operation function. * - * @name toString + * @static * @memberOf _ - * @category Chaining - * @returns {string} Returns the string result. + * @category Utility * @example * - * _([1, 2, 3]).toString(); - * // => '1,2,3' + * var object = { 'user': 'fred' }; + * _.noop(object) === undefined; + * // => true */ - function wrapperToString() { - return String(this.__wrapped__); + function noop() { + // No operation performed. } /** - * Extracts the wrapped value. + * Creates a function which returns the property value of `key` on a given object. * - * @name valueOf + * @static * @memberOf _ - * @alias value - * @category Chaining - * @returns {*} Returns the wrapped value. + * @category Utility + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. * @example * - * _([1, 2, 3]).valueOf(); - * // => [1, 2, 3] + * var users = [ + * { 'user': 'fred' }, + * { 'user': 'barney' } + * ]; + * + * var getName = _.property('user'); + * + * _.map(users, getName); + * // => ['fred', barney'] + * + * _.pluck(_.sortBy(users, getName), 'user'); + * // => ['barney', 'fred'] */ - function wrapperValueOf() { - return this.__wrapped__; + function property(key) { + return baseProperty(key + ''); } - /*--------------------------------------------------------------------------*/ + /** + * The inverse of `_.property`; this method creates a function which returns + * the property value of a given key on `object`. + * + * @static + * @memberOf _ + * @category Utility + * @param {Object} object The object to inspect. + * @returns {Function} Returns the new function. + * @example + * + * var object = { 'user': 'fred', 'age': 40, 'active': true }; + * _.map(['active', 'user'], _.propertyOf(object)); + * // => [true, 'fred'] + * + * var object = { 'a': 3, 'b': 1, 'c': 2 }; + * _.sortBy(['a', 'b', 'c'], _.propertyOf(object)); + * // => ['b', 'c', 'a'] + */ + function propertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } - // add functions that return wrapped values when chaining + /** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to, but not including, `end`. If `start` is less than `end` a + * zero-length range is created unless a negative `step` is specified. + * + * @static + * @memberOf _ + * @category Utility + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the new array of numbers. + * @example + * + * _.range(4); + * // => [0, 1, 2, 3] + * + * _.range(1, 5); + * // => [1, 2, 3, 4] + * + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] + */ + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = null; + } + start = +start || 0; + step = step == null ? 1 : (+step || 0); + + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + // Use `Array(length)` so engines like Chakra and V8 avoid slower modes. + // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details. + var index = -1, + length = nativeMax(ceil((end - start) / (step || 1)), 0), + result = Array(length); + + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + + /** + * Invokes the iteratee function `n` times, returning an array of the results + * of each invocation. The `iteratee` is bound to `thisArg` and invoked with + * one argument; (index). + * + * @static + * @memberOf _ + * @category Utility + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the array of results. + * @example + * + * var diceRolls = _.times(3, _.partial(_.random, 1, 6, false)); + * // => [3, 6, 4] + * + * _.times(3, function(n) { mage.castSpell(n); }); + * // => invokes `mage.castSpell(n)` three times with `n` of `0`, `1`, and `2` respectively + * + * _.times(3, function(n) { this.cast(n); }, mage); + * // => also invokes `mage.castSpell(n)` three times + */ + function times(n, iteratee, thisArg) { + n = +n; + + // Exit early to avoid a JSC JIT bug in Safari 8 + // where `Array(0)` is treated as `Array(1)`. + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, + result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + + /** + * Generates a unique ID. If `prefix` is provided the ID is appended to it. + * + * @static + * @memberOf _ + * @category Utility + * @param {string} [prefix] The value to prefix the ID with. + * @returns {string} Returns the unique ID. + * @example + * + * _.uniqueId('contact_'); + * // => 'contact_104' + * + * _.uniqueId(); + * // => '105' + */ + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + + /*------------------------------------------------------------------------*/ + + // Ensure `new LodashWrapper` is an instance of `lodash`. + LodashWrapper.prototype = lodash.prototype; + + // Add functions to the `Map` cache. + MapCache.prototype['delete'] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + + // Add functions to the `Set` cache. + SetCache.prototype.push = cachePush; + + // Assign cache to `_.memoize`. + memoize.Cache = MapCache; + + // Add functions that return wrapped values when chaining. lodash.after = after; + lodash.ary = ary; lodash.assign = assign; lodash.at = at; + lodash.before = before; lodash.bind = bind; lodash.bindAll = bindAll; lodash.bindKey = bindKey; + lodash.callback = callback; lodash.chain = chain; + lodash.chunk = chunk; lodash.compact = compact; - lodash.compose = compose; lodash.constant = constant; lodash.countBy = countBy; lodash.create = create; - lodash.createCallback = createCallback; lodash.curry = curry; + lodash.curryRight = curryRight; lodash.debounce = debounce; lodash.defaults = defaults; lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; lodash.filter = filter; lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; lodash.forEach = forEach; lodash.forEachRight = forEachRight; lodash.forIn = forIn; lodash.forInRight = forInRight; lodash.forOwn = forOwn; @@ -6898,260 +10635,427 @@ lodash.initial = initial; lodash.intersection = intersection; lodash.invert = invert; lodash.invoke = invoke; lodash.keys = keys; + lodash.keysIn = keysIn; lodash.map = map; lodash.mapValues = mapValues; - lodash.max = max; + lodash.matches = matches; lodash.memoize = memoize; lodash.merge = merge; - lodash.min = min; + lodash.mixin = mixin; + lodash.negate = negate; lodash.omit = omit; lodash.once = once; lodash.pairs = pairs; lodash.partial = partial; lodash.partialRight = partialRight; + lodash.partition = partition; lodash.pick = pick; lodash.pluck = pluck; lodash.property = property; + lodash.propertyOf = propertyOf; lodash.pull = pull; + lodash.pullAt = pullAt; lodash.range = range; + lodash.rearg = rearg; lodash.reject = reject; lodash.remove = remove; lodash.rest = rest; lodash.shuffle = shuffle; + lodash.slice = slice; lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; lodash.tap = tap; lodash.throttle = throttle; + lodash.thru = thru; lodash.times = times; lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; lodash.transform = transform; lodash.union = union; lodash.uniq = uniq; + lodash.unzip = unzip; lodash.values = values; + lodash.valuesIn = valuesIn; lodash.where = where; lodash.without = without; lodash.wrap = wrap; lodash.xor = xor; lodash.zip = zip; lodash.zipObject = zipObject; - // add aliases + // Add aliases. + lodash.backflow = flowRight; lodash.collect = map; - lodash.drop = rest; + lodash.compose = flowRight; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; + lodash.iteratee = callback; lodash.methods = functions; lodash.object = zipObject; lodash.select = filter; lodash.tail = rest; lodash.unique = uniq; - lodash.unzip = zip; - // add functions to `lodash.prototype` - mixin(lodash); + // Add functions to `lodash.prototype`. + mixin(lodash, lodash); - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ - // add functions that return unwrapped values when chaining + // Add functions that return unwrapped values when chaining. + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; lodash.clone = clone; lodash.cloneDeep = cloneDeep; - lodash.contains = contains; + lodash.deburr = deburr; + lodash.endsWith = endsWith; lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; lodash.every = every; lodash.find = find; lodash.findIndex = findIndex; lodash.findKey = findKey; lodash.findLast = findLast; lodash.findLastIndex = findLastIndex; lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; lodash.has = has; lodash.identity = identity; + lodash.includes = includes; lodash.indexOf = indexOf; lodash.isArguments = isArguments; lodash.isArray = isArray; lodash.isBoolean = isBoolean; lodash.isDate = isDate; lodash.isElement = isElement; lodash.isEmpty = isEmpty; lodash.isEqual = isEqual; + lodash.isError = isError; lodash.isFinite = isFinite; lodash.isFunction = isFunction; + lodash.isMatch = isMatch; lodash.isNaN = isNaN; + lodash.isNative = isNative; lodash.isNull = isNull; lodash.isNumber = isNumber; lodash.isObject = isObject; lodash.isPlainObject = isPlainObject; lodash.isRegExp = isRegExp; lodash.isString = isString; + lodash.isTypedArray = isTypedArray; lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; lodash.lastIndexOf = lastIndexOf; - lodash.mixin = mixin; + lodash.max = max; + lodash.min = min; lodash.noConflict = noConflict; lodash.noop = noop; lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; lodash.parseInt = parseInt; lodash.random = random; lodash.reduce = reduce; lodash.reduceRight = reduceRight; + lodash.repeat = repeat; lodash.result = result; lodash.runInContext = runInContext; lodash.size = size; + lodash.snakeCase = snakeCase; lodash.some = some; lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; lodash.unescape = unescape; lodash.uniqueId = uniqueId; + lodash.words = words; - // add aliases + // Add aliases. lodash.all = every; lodash.any = some; + lodash.contains = includes; lodash.detect = find; - lodash.findWhere = find; lodash.foldl = reduce; lodash.foldr = reduceRight; - lodash.include = contains; + lodash.head = first; + lodash.include = includes; lodash.inject = reduce; - mixin(function() { - var source = {} - forOwn(lodash, function(func, methodName) { + mixin(lodash, (function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { if (!lodash.prototype[methodName]) { source[methodName] = func; } }); return source; - }(), false); + }()), false); - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ - // add functions capable of returning wrapped and unwrapped values when chaining - lodash.first = first; - lodash.last = last; + // Add functions capable of returning wrapped and unwrapped values when chaining. lodash.sample = sample; - // add aliases - lodash.take = first; - lodash.head = first; - - forOwn(lodash, function(func, methodName) { - var callbackable = methodName !== 'sample'; - if (!lodash.prototype[methodName]) { - lodash.prototype[methodName]= function(n, guard) { - var chainAll = this.__chain__, - result = func(this.__wrapped__, n, guard); - - return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function'))) - ? result - : new lodashWrapper(result, chainAll); - }; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); } - }); + return this.thru(function(value) { + return sample(value, n); + }); + }; - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** * The semantic version number. * * @static * @memberOf _ * @type string */ - lodash.VERSION = '2.4.1'; + lodash.VERSION = VERSION; - // add "Chaining" functions to the wrapper - lodash.prototype.chain = wrapperChain; - lodash.prototype.toString = wrapperToString; - lodash.prototype.value = wrapperValueOf; - lodash.prototype.valueOf = wrapperValueOf; + // Assign default placeholders. + arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) { + lodash[methodName].placeholder = lodash; + }); - // add `Array` functions that return unwrapped values - baseEach(['join', 'pop', 'shift'], function(methodName) { - var func = arrayRef[methodName]; - lodash.prototype[methodName] = function() { - var chainAll = this.__chain__, - result = func.apply(this.__wrapped__, arguments); + // Add `LazyWrapper` methods that accept an `iteratee` value. + arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { + var isFilter = index == LAZY_FILTER_FLAG; - return chainAll - ? new lodashWrapper(result, chainAll) - : result; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(), + filtered = result.filtered, + iteratees = result.iteratees || (result.iteratees = []); + + result.filtered = filtered || isFilter || (index == LAZY_WHILE_FLAG && result.dir < 0); + iteratees.push({ 'iteratee': getCallback(iteratee, thisArg, 3), 'type': index }); + return result; }; }); - // add `Array` functions that return the existing wrapped value - baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) { - var func = arrayRef[methodName]; + // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. + arrayEach(['drop', 'take'], function(methodName, index) { + var countName = methodName + 'Count', + whileName = methodName + 'While'; + + LazyWrapper.prototype[methodName] = function(n) { + n = n == null ? 1 : nativeMax(+n || 0, 0); + + var result = this.clone(); + if (result.filtered) { + var value = result[countName]; + result[countName] = index ? nativeMin(value, n) : (value + n); + } else { + var views = result.views || (result.views = []); + views.push({ 'size': n, 'type': methodName + (result.dir < 0 ? 'Right' : '') }); + } + return result; + }; + + LazyWrapper.prototype[methodName + 'Right'] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + + LazyWrapper.prototype[methodName + 'RightWhile'] = function(predicate, thisArg) { + return this.reverse()[whileName](predicate, thisArg).reverse(); + }; + }); + + // Add `LazyWrapper` methods for `_.first` and `_.last`. + arrayEach(['first', 'last'], function(methodName, index) { + var takeName = 'take' + (index ? 'Right': ''); + + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + + // Add `LazyWrapper` methods for `_.initial` and `_.rest`. + arrayEach(['initial', 'rest'], function(methodName, index) { + var dropName = 'drop' + (index ? '' : 'Right'); + + LazyWrapper.prototype[methodName] = function() { + return this[dropName](1); + }; + }); + + // Add `LazyWrapper` methods for `_.pluck` and `_.where`. + arrayEach(['pluck', 'where'], function(methodName, index) { + var operationName = index ? 'filter' : 'map', + createCallback = index ? baseMatches : baseProperty; + + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(index ? value : (value + ''))); + }; + }); + + LazyWrapper.prototype.dropWhile = function(iteratee, thisArg) { + var done, + lastIndex, + isRight = this.dir < 0; + + iteratee = getCallback(iteratee, thisArg, 3); + return this.filter(function(value, index, array) { + done = done && (isRight ? index < lastIndex : index > lastIndex); + lastIndex = index; + return done || (done = !iteratee(value, index, array)); + }); + }; + + LazyWrapper.prototype.reject = function(iteratee, thisArg) { + iteratee = getCallback(iteratee, thisArg, 3); + return this.filter(function(value, index, array) { + return !iteratee(value, index, array); + }); + }; + + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : (+start || 0); + var result = start < 0 ? this.takeRight(-start) : this.drop(start); + + if (typeof end != 'undefined') { + end = (+end || 0); + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + + // Add `LazyWrapper` methods to `lodash.prototype`. + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName], + retUnwrapped = /^(?:first|last)$/.test(methodName); + lodash.prototype[methodName] = function() { - func.apply(this.__wrapped__, arguments); - return this; + var value = this.__wrapped__, + args = arguments, + chainAll = this.__chain__, + isHybrid = !!this.__actions__.length, + isLazy = value instanceof LazyWrapper, + onlyLazy = isLazy && !isHybrid; + + if (retUnwrapped && !chainAll) { + return onlyLazy + ? func.call(value) + : lodashFunc.call(lodash, this.value()); + } + var interceptor = function(value) { + var otherArgs = [value]; + push.apply(otherArgs, args); + return lodashFunc.apply(lodash, otherArgs); + }; + if (isLazy || isArray(value)) { + var wrapper = onlyLazy ? value : new LazyWrapper(this), + result = func.apply(wrapper, args); + + if (!retUnwrapped && (isHybrid || result.actions)) { + var actions = result.actions || (result.actions = []); + actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + } + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); }; }); - // add `Array` functions that return new wrapped values - baseEach(['concat', 'slice', 'splice'], function(methodName) { - var func = arrayRef[methodName]; + // Add `Array.prototype` functions to `lodash.prototype`. + arrayEach(['concat', 'join', 'pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { + var arrayFunc = arrayProto[methodName], + chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', + fixObjects = !support.spliceObjects && /^(?:pop|shift|splice)$/.test(methodName), + retUnwrapped = /^(?:join|pop|shift)$/.test(methodName); + + // Avoid array-like object bugs with `Array#shift` and `Array#splice` in + // IE < 9, Firefox < 10, Narwhal, and RingoJS. + var func = !fixObjects ? arrayFunc : function() { + var result = arrayFunc.apply(this, arguments); + if (this.length === 0) { + delete this[0]; + } + return result; + }; + lodash.prototype[methodName] = function() { - return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__); + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); }; }); - // avoid array-like object bugs with `Array#shift` and `Array#splice` - // in IE < 9, Firefox < 10, Narwhal, and RingoJS - if (!support.spliceObjects) { - baseEach(['pop', 'shift', 'splice'], function(methodName) { - var func = arrayRef[methodName], - isSplice = methodName == 'splice'; + // Add functions to the lazy wrapper. + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; - lodash.prototype[methodName] = function() { - var chainAll = this.__chain__, - value = this.__wrapped__, - result = func.apply(value, arguments); + // Add chaining functions to the lodash wrapper. + lodash.prototype.chain = wrapperChain; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; - if (value.length === 0) { - delete value[0]; - } - return (chainAll || isSplice) - ? new lodashWrapper(result, chainAll) - : result; - }; - }); - } + // Add function aliases to the lodash wrapper. + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; return lodash; } /*--------------------------------------------------------------------------*/ - // expose Lo-Dash + // Export lodash. var _ = runInContext(); - // some AMD build optimizers like r.js check for condition patterns like the following: + // Some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose Lo-Dash to the global object even when an AMD loader is present in - // case Lo-Dash is loaded with a RequireJS shim config. - // See http://requirejs.org/docs/api.html#config-shim + // Expose lodash to the global object when an AMD loader is present to avoid + // errors in cases where lodash is loaded by a script tag and not intended + // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch for + // more details. root._ = _; - // define as an anonymous module so, through path mapping, it can be - // referenced as the "underscore" module + // Define as an anonymous module so, through path mapping, it can be + // referenced as the "underscore" module. define(function() { return _; }); } - // check for `exports` after `define` in case a build optimizer adds an `exports` object + // Check for `exports` after `define` in case a build optimizer adds an `exports` object. else if (freeExports && freeModule) { - // in Node.js or RingoJS + // Export for Node.js or RingoJS. if (moduleExports) { (freeModule.exports = _)._ = _; } - // in Narwhal or Rhino -require + // Export for Narwhal or Rhino -require. else { freeExports._ = _; } } else { - // in a browser or Rhino + // Export for a browser or Rhino. root._ = _; } }.call(this));