PageRenderTime 50ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs//0.4.2/lodash.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 1529 lines | 1441 code | 27 blank | 61 comment | 16 complexity | 3cd0b3bf760fe2edf256c44c3d9d97cc MD5 | raw file
  1. /*!
  2. * Lo-Dash v0.4.2 <http://lodash.com>
  3. * Copyright 2012 John-David Dalton <http://allyoucanleet.com/>
  4. * Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
  5. * <http://documentcloud.github.com/underscore>
  6. * Available under MIT license <http://lodash.com/license>
  7. */
  8. ;(function(window, undefined) {
  9. 'use strict';
  10. /**
  11. * Used to cache the last `_.templateSettings.evaluate` delimiter to avoid
  12. * unnecessarily assigning `reEvaluateDelimiter` a new generated regexp.
  13. * Assigned in `_.template`.
  14. */
  15. var lastEvaluateDelimiter;
  16. /**
  17. * Used to cache the last template `options.variable` to avoid unnecessarily
  18. * assigning `reDoubleVariable` a new generated regexp. Assigned in `_.template`.
  19. */
  20. var lastVariable;
  21. /**
  22. * Used to match potentially incorrect data object references, like `obj.obj`,
  23. * in compiled templates. Assigned in `_.template`.
  24. */
  25. var reDoubleVariable;
  26. /**
  27. * Used to match "evaluate" delimiters, including internal delimiters,
  28. * in template text. Assigned in `_.template`.
  29. */
  30. var reEvaluateDelimiter;
  31. /** Detect free variable `exports` */
  32. var freeExports = typeof exports == 'object' && exports &&
  33. (typeof global == 'object' && global && global == global.global && (window = global), exports);
  34. /** Native prototype shortcuts */
  35. var ArrayProto = Array.prototype,
  36. ObjectProto = Object.prototype;
  37. /** Used to generate unique IDs */
  38. var idCounter = 0;
  39. /** Used to restore the original `_` reference in `noConflict` */
  40. var oldDash = window._;
  41. /** Used to detect delimiter values that should be processed by `tokenizeEvaluate` */
  42. var reComplexDelimiter = /[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
  43. /** Used to match empty string literals in compiled template source */
  44. var reEmptyStringLeading = /\b__p \+= '';/g,
  45. reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
  46. reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
  47. /** Used to insert the data object variable into compiled template source */
  48. var reInsertVariable = /(?:__e|__t = )\(\s*(?![\d\s"']|this\.)/g;
  49. /** Used to detect if a method is native */
  50. var reNative = RegExp('^' +
  51. (ObjectProto.valueOf + '')
  52. .replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')
  53. .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
  54. );
  55. /** Used to match tokens in template text */
  56. var reToken = /__token__(\d+)/g;
  57. /** Used to match unescaped characters in strings for inclusion in HTML */
  58. var reUnescapedHtml = /[&<"']/g;
  59. /** Used to match unescaped characters in compiled string literals */
  60. var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
  61. /** Used to fix the JScript [[DontEnum]] bug */
  62. var shadowed = [
  63. 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
  64. 'toLocaleString', 'toString', 'valueOf'
  65. ];
  66. /** Used to make template sourceURLs easier to identify */
  67. var templateCounter = 0;
  68. /** Used to replace template delimiters */
  69. var token = '__token__';
  70. /** Used to store tokenized template text snippets */
  71. var tokenized = [];
  72. /** Native method shortcuts */
  73. var concat = ArrayProto.concat,
  74. hasOwnProperty = ObjectProto.hasOwnProperty,
  75. push = ArrayProto.push,
  76. propertyIsEnumerable = ObjectProto.propertyIsEnumerable,
  77. slice = ArrayProto.slice,
  78. toString = ObjectProto.toString;
  79. /* Native method shortcuts for methods with the same name as other `lodash` methods */
  80. var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
  81. nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
  82. nativeIsFinite = window.isFinite,
  83. nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys;
  84. /** `Object#toString` result shortcuts */
  85. var arrayClass = '[object Array]',
  86. boolClass = '[object Boolean]',
  87. dateClass = '[object Date]',
  88. funcClass = '[object Function]',
  89. numberClass = '[object Number]',
  90. regexpClass = '[object RegExp]',
  91. stringClass = '[object String]';
  92. /** Timer shortcuts */
  93. var clearTimeout = window.clearTimeout,
  94. setTimeout = window.setTimeout;
  95. /**
  96. * Detect the JScript [[DontEnum]] bug:
  97. * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
  98. * made non-enumerable as well.
  99. */
  100. var hasDontEnumBug = !propertyIsEnumerable.call({ 'valueOf': 0 }, 'valueOf');
  101. /** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */
  102. var noArraySliceOnStrings = slice.call('x')[0] != 'x';
  103. /**
  104. * Detect lack of support for accessing string characters by index:
  105. * IE < 8 can't access characters by index and IE 8 can only access
  106. * characters by index on string literals.
  107. */
  108. var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
  109. /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
  110. var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
  111. /* Detect if `Object.keys` exists and is inferred to be fast (V8, Opera, IE) */
  112. var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
  113. /** Detect if sourceURL syntax is usable without erroring */
  114. try {
  115. // Adobe's and Narwhal's JS engines will error
  116. var useSourceURL = (Function('//@')(), true);
  117. } catch(e){ }
  118. /**
  119. * Used to escape characters for inclusion in HTML.
  120. * The `>` and `/` characters don't require escaping in HTML and have no
  121. * special meaning unless they're part of a tag or an unquoted attribute value
  122. * http://mathiasbynens.be/notes/ambiguous-ampersands (semi-related fun fact)
  123. */
  124. var htmlEscapes = {
  125. '&': '&amp;',
  126. '<': '&lt;',
  127. '"': '&quot;',
  128. "'": '&#x27;'
  129. };
  130. /** Used to determine if values are of the language type Object */
  131. var objectTypes = {
  132. 'boolean': false,
  133. 'function': true,
  134. 'object': true,
  135. 'number': false,
  136. 'string': false,
  137. 'undefined': false
  138. };
  139. /** Used to escape characters for inclusion in compiled string literals */
  140. var stringEscapes = {
  141. '\\': '\\',
  142. "'": "'",
  143. '\n': 'n',
  144. '\r': 'r',
  145. '\t': 't',
  146. '\u2028': 'u2028',
  147. '\u2029': 'u2029'
  148. };
  149. /*--------------------------------------------------------------------------*/
  150. /**
  151. * The `lodash` function.
  152. *
  153. * @name _
  154. * @constructor
  155. * @param {Mixed} value The value to wrap in a `LoDash` instance.
  156. * @returns {Object} Returns a `LoDash` instance.
  157. */
  158. function lodash(value) {
  159. // allow invoking `lodash` without the `new` operator
  160. return new LoDash(value);
  161. }
  162. /**
  163. * Creates a `LoDash` instance that wraps a value to allow chaining.
  164. *
  165. * @private
  166. * @constructor
  167. * @param {Mixed} value The value to wrap.
  168. */
  169. function LoDash(value) {
  170. // exit early if already wrapped
  171. if (value && value._wrapped) {
  172. return value;
  173. }
  174. this._wrapped = value;
  175. }
  176. /**
  177. * By default, Lo-Dash uses embedded Ruby (ERB) style template delimiters,
  178. * change the following template settings to use alternative delimiters.
  179. *
  180. * @static
  181. * @memberOf _
  182. * @type Object
  183. */
  184. lodash.templateSettings = {
  185. /**
  186. * Used to detect `data` property values to be HTML-escaped.
  187. *
  188. * @static
  189. * @memberOf _.templateSettings
  190. * @type RegExp
  191. */
  192. 'escape': /<%-([\s\S]+?)%>/g,
  193. /**
  194. * Used to detect code to be evaluated.
  195. *
  196. * @static
  197. * @memberOf _.templateSettings
  198. * @type RegExp
  199. */
  200. 'evaluate': /<%([\s\S]+?)%>/g,
  201. /**
  202. * Used to detect `data` property values to inject.
  203. *
  204. * @static
  205. * @memberOf _.templateSettings
  206. * @type RegExp
  207. */
  208. 'interpolate': /<%=([\s\S]+?)%>/g,
  209. /**
  210. * Used to reference the data object in the template text.
  211. *
  212. * @static
  213. * @memberOf _.templateSettings
  214. * @type String
  215. */
  216. 'variable': 'obj'
  217. };
  218. /*--------------------------------------------------------------------------*/
  219. /**
  220. * The template used to create iterator functions.
  221. *
  222. * @private
  223. * @param {Obect} data The data object used to populate the text.
  224. * @returns {String} Returns the interpolated text.
  225. */
  226. var iteratorTemplate = template(
  227. // conditional strict mode
  228. '<% if (useStrict) { %>\'use strict\';\n<% } %>' +
  229. // the `iteratee` may be reassigned by the `top` snippet
  230. 'var index, iteratee = <%= firstArg %>, ' +
  231. // assign the `result` variable an initial value
  232. 'result<% if (init) { %> = <%= init %><% } %>;\n' +
  233. // add code to exit early or do so if the first argument is falsey
  234. '<%= exit %>;\n' +
  235. // add code after the exit snippet but before the iteration branches
  236. '<%= top %>;\n' +
  237. // the following branch is for iterating arrays and array-like objects
  238. '<% if (arrayBranch) { %>' +
  239. 'var length = iteratee.length; index = -1;' +
  240. ' <% if (objectBranch) { %>\nif (length === length >>> 0) {<% } %>' +
  241. // add support for accessing string characters by index if needed
  242. ' <% if (noCharByIndex) { %>\n' +
  243. ' if (toString.call(iteratee) == stringClass) {\n' +
  244. ' iteratee = iteratee.split(\'\')\n' +
  245. ' }' +
  246. ' <% } %>\n' +
  247. ' <%= arrayBranch.beforeLoop %>;\n' +
  248. ' while (++index < length) {\n' +
  249. ' <%= arrayBranch.inLoop %>\n' +
  250. ' }' +
  251. ' <% if (objectBranch) { %>\n}<% } %>' +
  252. '<% } %>' +
  253. // the following branch is for iterating an object's own/inherited properties
  254. '<% if (objectBranch) { %>' +
  255. ' <% if (arrayBranch) { %>\nelse {<% } %>' +
  256. ' <% if (!hasDontEnumBug) { %>\n' +
  257. ' var skipProto = typeof iteratee == \'function\' && \n' +
  258. ' propertyIsEnumerable.call(iteratee, \'prototype\');\n' +
  259. ' <% } %>' +
  260. // iterate own properties using `Object.keys` if it's fast
  261. ' <% if (isKeysFast && useHas) { %>\n' +
  262. ' var props = nativeKeys(iteratee),\n' +
  263. ' propIndex = -1,\n' +
  264. ' length = props.length;\n\n' +
  265. ' <%= objectBranch.beforeLoop %>;\n' +
  266. ' while (++propIndex < length) {\n' +
  267. ' index = props[propIndex];\n' +
  268. ' if (!(skipProto && index == \'prototype\')) {\n' +
  269. ' <%= objectBranch.inLoop %>\n' +
  270. ' }\n' +
  271. ' }' +
  272. // else using a for-in loop
  273. ' <% } else { %>\n' +
  274. ' <%= objectBranch.beforeLoop %>;\n' +
  275. ' for (index in iteratee) {' +
  276. ' <% if (hasDontEnumBug) { %>\n' +
  277. ' <% if (useHas) { %>if (hasOwnProperty.call(iteratee, index)) {\n <% } %>' +
  278. ' <%= objectBranch.inLoop %>;\n' +
  279. ' <% if (useHas) { %>}<% } %>' +
  280. ' <% } else { %>\n' +
  281. // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
  282. // (if the prototype or a property on the prototype has been set)
  283. // incorrectly sets a function's `prototype` property [[Enumerable]]
  284. // value to `true`. Because of this Lo-Dash standardizes on skipping
  285. // the the `prototype` property of functions regardless of its
  286. // [[Enumerable]] value.
  287. ' if (!(skipProto && index == \'prototype\')<% if (useHas) { %> &&\n' +
  288. ' hasOwnProperty.call(iteratee, index)<% } %>) {\n' +
  289. ' <%= objectBranch.inLoop %>\n' +
  290. ' }' +
  291. ' <% } %>\n' +
  292. ' }' +
  293. ' <% } %>' +
  294. // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
  295. // existing property and the `constructor` property of a prototype
  296. // defaults to non-enumerable, Lo-Dash skips the `constructor`
  297. // property when it infers it's iterating over a `prototype` object.
  298. ' <% if (hasDontEnumBug) { %>\n\n' +
  299. ' var ctor = iteratee.constructor;\n' +
  300. ' <% for (var k = 0; k < 7; k++) { %>\n' +
  301. ' index = \'<%= shadowed[k] %>\';\n' +
  302. ' if (<%' +
  303. ' if (shadowed[k] == \'constructor\') {' +
  304. ' %>!(ctor && ctor.prototype === iteratee) && <%' +
  305. ' } %>hasOwnProperty.call(iteratee, index)) {\n' +
  306. ' <%= objectBranch.inLoop %>\n' +
  307. ' }' +
  308. ' <% } %>' +
  309. ' <% } %>' +
  310. ' <% if (arrayBranch) { %>\n}<% } %>' +
  311. '<% } %>\n' +
  312. // add code to the bottom of the iteration function
  313. '<%= bottom %>;\n' +
  314. // finally, return the `result`
  315. 'return result'
  316. );
  317. /**
  318. * Reusable iterator options shared by
  319. * `every`, `filter`, `find`, `forEach`, `forIn`, `forOwn`, `groupBy`, `map`,
  320. * `reject`, `some`, and `sortBy`.
  321. */
  322. var baseIteratorOptions = {
  323. 'args': 'collection, callback, thisArg',
  324. 'init': 'collection',
  325. 'top':
  326. 'if (!callback) {\n' +
  327. ' callback = identity\n' +
  328. '}\n' +
  329. 'else if (thisArg) {\n' +
  330. ' callback = iteratorBind(callback, thisArg)\n' +
  331. '}',
  332. 'inLoop': 'callback(iteratee[index], index, collection)'
  333. };
  334. /** Reusable iterator options for `every` and `some` */
  335. var everyIteratorOptions = {
  336. 'init': 'true',
  337. 'inLoop': 'if (!callback(iteratee[index], index, collection)) return !result'
  338. };
  339. /** Reusable iterator options for `defaults` and `extend` */
  340. var extendIteratorOptions = {
  341. 'useHas': false,
  342. 'useStrict': false,
  343. 'args': 'object',
  344. 'init': 'object',
  345. 'top':
  346. 'for (var iterateeIndex = 1, length = arguments.length; iterateeIndex < length; iterateeIndex++) {\n' +
  347. ' iteratee = arguments[iterateeIndex];\n' +
  348. (hasDontEnumBug ? ' if (iteratee) {' : ''),
  349. 'inLoop': 'result[index] = iteratee[index]',
  350. 'bottom': (hasDontEnumBug ? ' }\n' : '') + '}'
  351. };
  352. /** Reusable iterator options for `filter` and `reject` */
  353. var filterIteratorOptions = {
  354. 'init': '[]',
  355. 'inLoop': 'callback(iteratee[index], index, collection) && result.push(iteratee[index])'
  356. };
  357. /** Reusable iterator options for `find`, `forEach`, `forIn`, and `forOwn` */
  358. var forEachIteratorOptions = {
  359. 'top': 'if (thisArg) callback = iteratorBind(callback, thisArg)'
  360. };
  361. /** Reusable iterator options for `forIn` and `forOwn` */
  362. var forOwnIteratorOptions = {
  363. 'inLoop': {
  364. 'object': baseIteratorOptions.inLoop
  365. }
  366. };
  367. /** Reusable iterator options for `invoke`, `map`, `pluck`, and `sortBy` */
  368. var mapIteratorOptions = {
  369. 'init': '',
  370. 'exit': 'if (!collection) return []',
  371. 'beforeLoop': {
  372. 'array': 'result = Array(length)',
  373. 'object': 'result = ' + (isKeysFast ? 'Array(length)' : '[]')
  374. },
  375. 'inLoop': {
  376. 'array': 'result[index] = callback(iteratee[index], index, collection)',
  377. 'object': 'result' + (isKeysFast ? '[propIndex] = ' : '.push') + '(callback(iteratee[index], index, collection))'
  378. }
  379. };
  380. /*--------------------------------------------------------------------------*/
  381. /**
  382. * Creates a new function optimized for searching large arrays for a given `value`,
  383. * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
  384. *
  385. * @private
  386. * @param {Array} array The array to search.
  387. * @param {Mixed} value The value to search for.
  388. * @param {Number} [fromIndex=0] The index to start searching from.
  389. * @param {Number} [largeSize=30] The length at which an array is considered large.
  390. * @returns {Boolean} Returns `true` if `value` is found, else `false`.
  391. */
  392. function cachedContains(array, fromIndex, largeSize) {
  393. fromIndex || (fromIndex = 0);
  394. var length = array.length,
  395. isLarge = (length - fromIndex) >= (largeSize || 30),
  396. cache = isLarge ? {} : array;
  397. if (isLarge) {
  398. // init value cache
  399. var key,
  400. index = fromIndex - 1;
  401. while (++index < length) {
  402. // manually coerce `value` to string because `hasOwnProperty`, in some
  403. // older versions of Firefox, coerces objects incorrectly
  404. key = array[index] + '';
  405. (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
  406. }
  407. }
  408. return function(value) {
  409. if (isLarge) {
  410. var key = value + '';
  411. return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
  412. }
  413. return indexOf(cache, value, fromIndex) > -1;
  414. }
  415. }
  416. /**
  417. * Creates compiled iteration functions. The iteration function will be created
  418. * to iterate over only objects if the first argument of `options.args` is
  419. * "object" or `options.inLoop.array` is falsey.
  420. *
  421. * @private
  422. * @param {Object} [options1, options2, ...] The compile options objects.
  423. *
  424. * useHas - A boolean to specify whether or not to use `hasOwnProperty` checks
  425. * in the object loop.
  426. *
  427. * useStrict - A boolean to specify whether or not to include the ES5
  428. * "use strict" directive.
  429. *
  430. * args - A string of comma separated arguments the iteration function will
  431. * accept.
  432. *
  433. * init - A string to specify the initial value of the `result` variable.
  434. *
  435. * exit - A string of code to use in place of the default exit-early check
  436. * of `if (!arguments[0]) return result`.
  437. *
  438. * top - A string of code to execute after the exit-early check but before
  439. * the iteration branches.
  440. *
  441. * beforeLoop - A string or object containing an "array" or "object" property
  442. * of code to execute before the array or object loops.
  443. *
  444. * inLoop - A string or object containing an "array" or "object" property
  445. * of code to execute in the array or object loops.
  446. *
  447. * bottom - A string of code to execute after the iteration branches but
  448. * before the `result` is returned.
  449. *
  450. * @returns {Function} Returns the compiled function.
  451. */
  452. function createIterator() {
  453. var object,
  454. prop,
  455. value,
  456. index = -1,
  457. length = arguments.length;
  458. // merge options into a template data object
  459. var data = {
  460. 'bottom': '',
  461. 'exit': '',
  462. 'init': '',
  463. 'top': '',
  464. 'arrayBranch': { 'beforeLoop': '' },
  465. 'objectBranch': { 'beforeLoop': '' }
  466. };
  467. while (++index < length) {
  468. object = arguments[index];
  469. for (prop in object) {
  470. value = (value = object[prop]) == null ? '' : value;
  471. // keep this regexp explicit for the build pre-process
  472. if (/beforeLoop|inLoop/.test(prop)) {
  473. if (typeof value == 'string') {
  474. value = { 'array': value, 'object': value };
  475. }
  476. data.arrayBranch[prop] = value.array;
  477. data.objectBranch[prop] = value.object;
  478. } else {
  479. data[prop] = value;
  480. }
  481. }
  482. }
  483. // set additional template `data` values
  484. var args = data.args,
  485. firstArg = /^[^,]+/.exec(args)[0];
  486. data.firstArg = firstArg;
  487. data.hasDontEnumBug = hasDontEnumBug;
  488. data.isKeysFast = isKeysFast;
  489. data.shadowed = shadowed;
  490. data.useHas = data.useHas !== false;
  491. data.useStrict = data.useStrict !== false;
  492. if (!('noCharByIndex' in data)) {
  493. data.noCharByIndex = noCharByIndex;
  494. }
  495. if (!data.exit) {
  496. data.exit = 'if (!' + firstArg + ') return result';
  497. }
  498. if (firstArg != 'collection' || !data.arrayBranch.inLoop) {
  499. data.arrayBranch = null;
  500. }
  501. // create the function factory
  502. var factory = Function(
  503. 'arrayClass, bind, compareAscending, funcClass, hasOwnProperty, identity, ' +
  504. 'iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice, ' +
  505. 'stringClass, toString',
  506. 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
  507. );
  508. // return the compiled function
  509. return factory(
  510. arrayClass, bind, compareAscending, funcClass, hasOwnProperty, identity,
  511. iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice,
  512. stringClass, toString
  513. );
  514. }
  515. /**
  516. * Used by `sortBy` to compare transformed values of `collection`, sorting
  517. * them in ascending order.
  518. *
  519. * @private
  520. * @param {Object} a The object to compare to `b`.
  521. * @param {Object} b The object to compare to `a`.
  522. * @returns {Number} Returns `-1` if `a` < `b`, `0` if `a` == `b`, or `1` if `a` > `b`.
  523. */
  524. function compareAscending(a, b) {
  525. a = a.criteria;
  526. b = b.criteria;
  527. if (a === undefined) {
  528. return 1;
  529. }
  530. if (b === undefined) {
  531. return -1;
  532. }
  533. return a < b ? -1 : a > b ? 1 : 0;
  534. }
  535. /**
  536. * Used by `template` to replace tokens with their corresponding code snippets.
  537. *
  538. * @private
  539. * @param {String} match The matched token.
  540. * @param {String} index The `tokenized` index of the code snippet.
  541. * @returns {String} Returns the code snippet.
  542. */
  543. function detokenize(match, index) {
  544. return tokenized[index];
  545. }
  546. /**
  547. * Used by `template` to escape characters for inclusion in compiled
  548. * string literals.
  549. *
  550. * @private
  551. * @param {String} match The matched character to escape.
  552. * @returns {String} Returns the escaped character.
  553. */
  554. function escapeStringChar(match) {
  555. return '\\' + stringEscapes[match];
  556. }
  557. /**
  558. * Used by `escape` to escape characters for inclusion in HTML.
  559. *
  560. * @private
  561. * @param {String} match The matched character to escape.
  562. * @returns {String} Returns the escaped character.
  563. */
  564. function escapeHtmlChar(match) {
  565. return htmlEscapes[match];
  566. }
  567. /**
  568. * Creates a new function that, when called, invokes `func` with the `this`
  569. * binding of `thisArg` and the arguments (value, index, object).
  570. *
  571. * @private
  572. * @param {Function} func The function to bind.
  573. * @param {Mixed} [thisArg] The `this` binding of `func`.
  574. * @returns {Function} Returns the new bound function.
  575. */
  576. function iteratorBind(func, thisArg) {
  577. return function(value, index, object) {
  578. return func.call(thisArg, value, index, object);
  579. };
  580. }
  581. /**
  582. * A no-operation function.
  583. *
  584. * @private
  585. */
  586. function noop() {
  587. // no operation performed
  588. }
  589. /**
  590. * A shim implementation of `Object.keys` that produces an array of the given
  591. * object's own enumerable property names.
  592. *
  593. * @private
  594. * @param {Object} object The object to inspect.
  595. * @returns {Array} Returns a new array of property names.
  596. */
  597. var shimKeys = createIterator({
  598. 'args': 'object',
  599. 'exit': 'if (!(object && objectTypes[typeof object])) throw TypeError()',
  600. 'init': '[]',
  601. 'inLoop': 'result.push(index)'
  602. });
  603. /**
  604. * Used by `template` to replace "escape" template delimiters with tokens.
  605. *
  606. * @private
  607. * @param {String} match The matched template delimiter.
  608. * @param {String} value The delimiter value.
  609. * @returns {String} Returns a token.
  610. */
  611. function tokenizeEscape(match, value) {
  612. if (reComplexDelimiter.test(value)) {
  613. return '<e%-' + value + '%>';
  614. }
  615. var index = tokenized.length;
  616. tokenized[index] = "' +\n__e(" + value + ") +\n'";
  617. return token + index;
  618. }
  619. /**
  620. * Used by `template` to replace "evaluate" template delimiters, or complex
  621. * "escape" and "interpolate" delimiters, with tokens.
  622. *
  623. * @private
  624. * @param {String} match The matched template delimiter.
  625. * @param {String} value The delimiter value.
  626. * @param {String} escapeValue The "escape" delimiter value.
  627. * @param {String} interpolateValue The "interpolate" delimiter value.
  628. * @returns {String} Returns a token.
  629. */
  630. function tokenizeEvaluate(match, value, escapeValue, interpolateValue) {
  631. var index = tokenized.length;
  632. if (value) {
  633. tokenized[index] = "';\n" + value + ";\n__p += '"
  634. } else if (escapeValue) {
  635. tokenized[index] = "' +\n__e(" + escapeValue + ") +\n'";
  636. } else if (interpolateValue) {
  637. tokenized[index] = "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
  638. }
  639. return token + index;
  640. }
  641. /**
  642. * Used by `template` to replace "interpolate" template delimiters with tokens.
  643. *
  644. * @private
  645. * @param {String} match The matched template delimiter.
  646. * @param {String} value The delimiter value.
  647. * @returns {String} Returns a token.
  648. */
  649. function tokenizeInterpolate(match, value) {
  650. if (reComplexDelimiter.test(value)) {
  651. return '<e%=' + value + '%>';
  652. }
  653. var index = tokenized.length;
  654. tokenized[index] = "' +\n((__t = (" + value + ")) == null ? '' : __t) +\n'";
  655. return token + index;
  656. }
  657. /*--------------------------------------------------------------------------*/
  658. /**
  659. * Checks if a given `target` value is present in a `collection` using strict
  660. * equality for comparisons, i.e. `===`.
  661. *
  662. * @static
  663. * @memberOf _
  664. * @alias include
  665. * @category Collections
  666. * @param {Array|Object|String} collection The collection to iterate over.
  667. * @param {Mixed} target The value to check for.
  668. * @returns {Boolean} Returns `true` if `target` value is found, else `false`.
  669. * @example
  670. *
  671. * _.contains([1, 2, 3], 3);
  672. * // => true
  673. *
  674. * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
  675. * // => true
  676. *
  677. * _.contains('curly', 'ur');
  678. * // => true
  679. */
  680. var contains = createIterator({
  681. 'args': 'collection, target',
  682. 'init': 'false',
  683. 'noCharByIndex': false,
  684. 'beforeLoop': {
  685. 'array': 'if (toString.call(iteratee) == stringClass) return collection.indexOf(target) > -1'
  686. },
  687. 'inLoop': 'if (iteratee[index] === target) return true'
  688. });
  689. /**
  690. * Checks if the `callback` returns a truthy value for **all** elements of a
  691. * `collection`. The `callback` is bound to `thisArg` and invoked with 3
  692. * arguments; (value, index|key, collection).
  693. *
  694. * @static
  695. * @memberOf _
  696. * @alias all
  697. * @category Collections
  698. * @param {Array|Object|String} collection The collection to iterate over.
  699. * @param {Function} [callback=identity] The function called per iteration.
  700. * @param {Mixed} [thisArg] The `this` binding for the callback.
  701. * @returns {Boolean} Returns `true` if all values pass the callback check, else `false`.
  702. * @example
  703. *
  704. * _.every([true, 1, null, 'yes'], Boolean);
  705. * // => false
  706. */
  707. var every = createIterator(baseIteratorOptions, everyIteratorOptions);
  708. /**
  709. * Examines each value in a `collection`, returning an array of all values the
  710. * `callback` returns truthy for. The `callback` is bound to `thisArg` and
  711. * invoked with 3 arguments; (value, index|key, collection).
  712. *
  713. * @static
  714. * @memberOf _
  715. * @alias select
  716. * @category Collections
  717. * @param {Array|Object|String} collection The collection to iterate over.
  718. * @param {Function} [callback=identity] The function called per iteration.
  719. * @param {Mixed} [thisArg] The `this` binding for the callback.
  720. * @returns {Array} Returns a new array of values that passed callback check.
  721. * @example
  722. *
  723. * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
  724. * // => [2, 4, 6]
  725. */
  726. var filter = createIterator(baseIteratorOptions, filterIteratorOptions);
  727. /**
  728. * Examines each value in a `collection`, returning the first one the `callback`
  729. * returns truthy for. The function returns as soon as it finds an acceptable
  730. * value, and does not iterate over the entire `collection`. The `callback` is
  731. * bound to `thisArg` and invoked with 3 arguments; (value, index|key, collection).
  732. *
  733. * @static
  734. * @memberOf _
  735. * @alias detect
  736. * @category Collections
  737. * @param {Array|Object|String} collection The collection to iterate over.
  738. * @param {Function} callback The function called per iteration.
  739. * @param {Mixed} [thisArg] The `this` binding for the callback.
  740. * @returns {Mixed} Returns the value that passed the callback check, else `undefined`.
  741. * @example
  742. *
  743. * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
  744. * // => 2
  745. */
  746. var find = createIterator(baseIteratorOptions, forEachIteratorOptions, {
  747. 'init': '',
  748. 'inLoop': 'if (callback(iteratee[index], index, collection)) return iteratee[index]'
  749. });
  750. /**
  751. * Iterates over a `collection`, executing the `callback` for each value in the
  752. * `collection`. The `callback` is bound to `thisArg` and invoked with 3
  753. * arguments; (value, index|key, collection).
  754. *
  755. * @static
  756. * @memberOf _
  757. * @alias each
  758. * @category Collections
  759. * @param {Array|Object|String} collection The collection to iterate over.
  760. * @param {Function} callback The function called per iteration.
  761. * @param {Mixed} [thisArg] The `this` binding for the callback.
  762. * @returns {Array|Object} Returns the `collection`.
  763. * @example
  764. *
  765. * _([1, 2, 3]).forEach(alert).join(',');
  766. * // => alerts each number and returns '1,2,3'
  767. *
  768. * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
  769. * // => alerts each number (order is not guaranteed)
  770. */
  771. var forEach = createIterator(baseIteratorOptions, forEachIteratorOptions);
  772. /**
  773. * Splits `collection` into sets, grouped by the result of running each value
  774. * through `callback`. The `callback` is bound to `thisArg` and invoked with
  775. * 3 arguments; (value, index|key, collection). The `callback` argument may
  776. * also be the name of a property to group by.
  777. *
  778. * @static
  779. * @memberOf _
  780. * @category Collections
  781. * @param {Array|Object|String} collection The collection to iterate over.
  782. * @param {Function|String} callback The function called per iteration or
  783. * property name to group by.
  784. * @param {Mixed} [thisArg] The `this` binding for the callback.
  785. * @returns {Object} Returns an object of grouped values.
  786. * @example
  787. *
  788. * _.groupBy([1.3, 2.1, 2.4], function(num) { return Math.floor(num); });
  789. * // => { '1': [1.3], '2': [2.1, 2.4] }
  790. *
  791. * _.groupBy([1.3, 2.1, 2.4], function(num) { return this.floor(num); }, Math);
  792. * // => { '1': [1.3], '2': [2.1, 2.4] }
  793. *
  794. * _.groupBy(['one', 'two', 'three'], 'length');
  795. * // => { '3': ['one', 'two'], '5': ['three'] }
  796. */
  797. var groupBy = createIterator(baseIteratorOptions, {
  798. 'init': '{}',
  799. 'top':
  800. 'var prop, isFunc = typeof callback == \'function\';\n' +
  801. 'if (isFunc && thisArg) callback = iteratorBind(callback, thisArg)',
  802. 'inLoop':
  803. 'prop = isFunc\n' +
  804. ' ? callback(iteratee[index], index, collection)\n' +
  805. ' : iteratee[index][callback];\n' +
  806. '(hasOwnProperty.call(result, prop) ? result[prop] : result[prop] = []).push(iteratee[index])'
  807. });
  808. /**
  809. * Invokes the method named by `methodName` on each element in the `collection`.
  810. * Additional arguments will be passed to each invoked method. If `methodName`
  811. * is a function it will be invoked for, and `this` bound to, each element
  812. * in the `collection`.
  813. *
  814. * @static
  815. * @memberOf _
  816. * @category Collections
  817. * @param {Array|Object|String} collection The collection to iterate over.
  818. * @param {Function|String} methodName The name of the method to invoke or
  819. * the function invoked per iteration.
  820. * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
  821. * @returns {Array} Returns a new array of values returned from each invoked method.
  822. * @example
  823. *
  824. * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
  825. * // => [[1, 5, 7], [1, 2, 3]]
  826. *
  827. * _.invoke([123, 456], String.prototype.split, '');
  828. * // => [['1', '2', '3'], ['4', '5', '6']]
  829. */
  830. var invoke = createIterator(mapIteratorOptions, {
  831. 'args': 'collection, methodName',
  832. 'top':
  833. 'var args = slice.call(arguments, 2),\n' +
  834. ' isFunc = typeof methodName == \'function\'',
  835. 'inLoop': {
  836. 'array':
  837. 'result[index] = (isFunc ? methodName : iteratee[index][methodName])' +
  838. '.apply(iteratee[index], args)',
  839. 'object':
  840. 'result' + (isKeysFast ? '[propIndex] = ' : '.push') +
  841. '((isFunc ? methodName : iteratee[index][methodName]).apply(iteratee[index], args))'
  842. }
  843. });
  844. /**
  845. * Produces a new array of values by mapping each element in the `collection`
  846. * through a transformation `callback`. The `callback` is bound to `thisArg`
  847. * and invoked with 3 arguments; (value, index|key, collection).
  848. *
  849. * @static
  850. * @memberOf _
  851. * @alias collect
  852. * @category Collections
  853. * @param {Array|Object|String} collection The collection to iterate over.
  854. * @param {Function} [callback=identity] The function called per iteration.
  855. * @param {Mixed} [thisArg] The `this` binding for the callback.
  856. * @returns {Array} Returns a new array of values returned by the callback.
  857. * @example
  858. *
  859. * _.map([1, 2, 3], function(num) { return num * 3; });
  860. * // => [3, 6, 9]
  861. *
  862. * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
  863. * // => [3, 6, 9] (order is not guaranteed)
  864. */
  865. var map = createIterator(baseIteratorOptions, mapIteratorOptions);
  866. /**
  867. * Retrieves the value of a specified property from all elements in
  868. * the `collection`.
  869. *
  870. * @static
  871. * @memberOf _
  872. * @category Collections
  873. * @param {Array|Object|String} collection The collection to iterate over.
  874. * @param {String} property The property to pluck.
  875. * @returns {Array} Returns a new array of property values.
  876. * @example
  877. *
  878. * var stooges = [
  879. * { 'name': 'moe', 'age': 40 },
  880. * { 'name': 'larry', 'age': 50 },
  881. * { 'name': 'curly', 'age': 60 }
  882. * ];
  883. *
  884. * _.pluck(stooges, 'name');
  885. * // => ['moe', 'larry', 'curly']
  886. */
  887. var pluck = createIterator(mapIteratorOptions, {
  888. 'args': 'collection, property',
  889. 'inLoop': {
  890. 'array': 'result[index] = iteratee[index][property]',
  891. 'object': 'result' + (isKeysFast ? '[propIndex] = ' : '.push') + '(iteratee[index][property])'
  892. }
  893. });
  894. /**
  895. * Boils down a `collection` to a single value. The initial state of the
  896. * reduction is `accumulator` and each successive step of it should be returned
  897. * by the `callback`. The `callback` is bound to `thisArg` and invoked with 4
  898. * arguments; for arrays they are (accumulator, value, index|key, collection).
  899. *
  900. * @static
  901. * @memberOf _
  902. * @alias foldl, inject
  903. * @category Collections
  904. * @param {Array|Object|String} collection The collection to iterate over.
  905. * @param {Function} callback The function called per iteration.
  906. * @param {Mixed} [accumulator] Initial value of the accumulator.
  907. * @param {Mixed} [thisArg] The `this` binding for the callback.
  908. * @returns {Mixed} Returns the accumulated value.
  909. * @example
  910. *
  911. * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
  912. * // => 6
  913. */
  914. var reduce = createIterator({
  915. 'args': 'collection, callback, accumulator, thisArg',
  916. 'init': 'accumulator',
  917. 'top':
  918. 'var noaccum = arguments.length < 3;\n' +
  919. 'if (thisArg) callback = iteratorBind(callback, thisArg)',
  920. 'beforeLoop': {
  921. 'array': 'if (noaccum) result = collection[++index]'
  922. },
  923. 'inLoop': {
  924. 'array':
  925. 'result = callback(result, iteratee[index], index, collection)',
  926. 'object':
  927. 'result = noaccum\n' +
  928. ' ? (noaccum = false, iteratee[index])\n' +
  929. ' : callback(result, iteratee[index], index, collection)'
  930. }
  931. });
  932. /**
  933. * The right-associative version of `_.reduce`.
  934. *
  935. * @static
  936. * @memberOf _
  937. * @alias foldr
  938. * @category Collections
  939. * @param {Array|Object|String} collection The collection to iterate over.
  940. * @param {Function} callback The function called per iteration.
  941. * @param {Mixed} [accumulator] Initial value of the accumulator.
  942. * @param {Mixed} [thisArg] The `this` binding for the callback.
  943. * @returns {Mixed} Returns the accumulated value.
  944. * @example
  945. *
  946. * var list = [[0, 1], [2, 3], [4, 5]];
  947. * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
  948. * // => [4, 5, 2, 3, 0, 1]
  949. */
  950. function reduceRight(collection, callback, accumulator, thisArg) {
  951. if (!collection) {
  952. return accumulator;
  953. }
  954. var length = collection.length,
  955. noaccum = arguments.length < 3;
  956. if(thisArg) {
  957. callback = iteratorBind(callback, thisArg);
  958. }
  959. if (length === length >>> 0) {
  960. var iteratee = noCharByIndex && toString.call(collection) == stringClass
  961. ? collection.split('')
  962. : collection;
  963. if (length && noaccum) {
  964. accumulator = iteratee[--length];
  965. }
  966. while (length--) {
  967. accumulator = callback(accumulator, iteratee[length], length, collection);
  968. }
  969. return accumulator;
  970. }
  971. var prop,
  972. props = keys(collection);
  973. length = props.length;
  974. if (length && noaccum) {
  975. accumulator = collection[props[--length]];
  976. }
  977. while (length--) {
  978. prop = props[length];
  979. accumulator = callback(accumulator, collection[prop], prop, collection);
  980. }
  981. return accumulator;
  982. }
  983. /**
  984. * The opposite of `_.filter`, this method returns the values of a
  985. * `collection` that `callback` does **not** return truthy for.
  986. *
  987. * @static
  988. * @memberOf _
  989. * @category Collections
  990. * @param {Array|Object|String} collection The collection to iterate over.
  991. * @param {Function} [callback=identity] The function called per iteration.
  992. * @param {Mixed} [thisArg] The `this` binding for the callback.
  993. * @returns {Array} Returns a new array of values that did **not** pass the callback check.
  994. * @example
  995. *
  996. * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
  997. * // => [1, 3, 5]
  998. */
  999. var reject = createIterator(baseIteratorOptions, filterIteratorOptions, {
  1000. 'inLoop': '!' + filterIteratorOptions.inLoop
  1001. });
  1002. /**
  1003. * Checks if the `callback` returns a truthy value for **any** element of a
  1004. * `collection`. The function returns as soon as it finds passing value, and
  1005. * does not iterate over the entire `collection`. The `callback` is bound to
  1006. * `thisArg` and invoked with 3 arguments; (value, index|key, collection).
  1007. *
  1008. * @static
  1009. * @memberOf _
  1010. * @alias any
  1011. * @category Collections
  1012. * @param {Array|Object|String} collection The collection to iterate over.
  1013. * @param {Function} [callback=identity] The function called per iteration.
  1014. * @param {Mixed} [thisArg] The `this` binding for the callback.
  1015. * @returns {Boolean} Returns `true` if any value passes the callback check, else `false`.
  1016. * @example
  1017. *
  1018. * _.some([null, 0, 'yes', false]);
  1019. * // => true
  1020. */
  1021. var some = createIterator(baseIteratorOptions, everyIteratorOptions, {
  1022. 'init': 'false',
  1023. 'inLoop': everyIteratorOptions.inLoop.replace('!', '')
  1024. });
  1025. /**
  1026. * Produces a new sorted array, sorted in ascending order by the results of
  1027. * running each element of `collection` through a transformation `callback`.
  1028. * The `callback` is bound to `thisArg` and invoked with 3 arguments;
  1029. * (value, index|key, collection). The `callback` argument may also be the
  1030. * name of a property to sort by (e.g. 'length').
  1031. *
  1032. * @static
  1033. * @memberOf _
  1034. * @category Collections
  1035. * @param {Array|Object|String} collection The collection to iterate over.
  1036. * @param {Function|String} callback The function called per iteration or
  1037. * property name to sort by.
  1038. * @param {Mixed} [thisArg] The `this` binding for the callback.
  1039. * @returns {Array} Returns a new array of sorted values.
  1040. * @example
  1041. *
  1042. * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
  1043. * // => [3, 1, 2]
  1044. *
  1045. * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
  1046. * // => [3, 1, 2]
  1047. *
  1048. * _.sortBy(['larry', 'brendan', 'moe'], 'length');
  1049. * // => ['moe', 'larry', 'brendan']
  1050. */
  1051. var sortBy = createIterator(baseIteratorOptions, mapIteratorOptions, {
  1052. 'top':
  1053. 'if (typeof callback == \'string\') {\n' +
  1054. ' var prop = callback;\n' +
  1055. ' callback = function(collection) { return collection[prop] }\n' +
  1056. '}\n' +
  1057. 'else if (thisArg) {\n' +
  1058. ' callback = iteratorBind(callback, thisArg)\n' +
  1059. '}',
  1060. 'inLoop': {
  1061. 'array':
  1062. 'result[index] = {\n' +
  1063. ' criteria: callback(iteratee[index], index, collection),\n' +
  1064. ' value: iteratee[index]\n' +
  1065. '}',
  1066. 'object':
  1067. 'result' + (isKeysFast ? '[propIndex] = ' : '.push') + '({\n' +
  1068. ' criteria: callback(iteratee[index], index, collection),\n' +
  1069. ' value: iteratee[index]\n' +
  1070. '})'
  1071. },
  1072. 'bottom':
  1073. 'result.sort(compareAscending);\n' +
  1074. 'length = result.length;\n' +
  1075. 'while (length--) {\n' +
  1076. ' result[length] = result[length].value\n' +
  1077. '}'
  1078. });
  1079. /**
  1080. * Converts the `collection`, into an array. Useful for converting the
  1081. * `arguments` object.
  1082. *
  1083. * @static
  1084. * @memberOf _
  1085. * @category Collections
  1086. * @param {Array|Object|String} collection The collection to convert.
  1087. * @returns {Array} Returns the new converted array.
  1088. * @example
  1089. *
  1090. * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
  1091. * // => [2, 3, 4]
  1092. */
  1093. function toArray(collection) {
  1094. if (!collection) {
  1095. return [];
  1096. }
  1097. if (collection.toArray && toString.call(collection.toArray) == funcClass) {
  1098. return collection.toArray();
  1099. }
  1100. var length = collection.length;
  1101. if (length === length >>> 0) {
  1102. return (noArraySliceOnStrings ? toString.call(collection) == stringClass : typeof collection == 'string')
  1103. ? collection.split('')
  1104. : slice.call(collection);
  1105. }
  1106. return values(collection);
  1107. }
  1108. /*--------------------------------------------------------------------------*/
  1109. /**
  1110. * Produces a new array with all falsey values of `array` removed. The values
  1111. * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
  1112. *
  1113. * @static
  1114. * @memberOf _
  1115. * @category Arrays
  1116. * @param {Array} array The array to compact.
  1117. * @returns {Array} Returns a new filtered array.
  1118. * @example
  1119. *
  1120. * _.compact([0, 1, false, 2, '', 3]);
  1121. * // => [1, 2, 3]
  1122. */
  1123. function compact(array) {
  1124. var result = [];
  1125. if (!array) {
  1126. return result;
  1127. }
  1128. var index = -1,
  1129. length = array.length;
  1130. while (++index < length) {
  1131. if (array[index]) {
  1132. result.push(array[index]);
  1133. }
  1134. }
  1135. return result;
  1136. }
  1137. /**
  1138. * Produces a new array of `array` values not present in the other arrays
  1139. * using strict equality for comparisons, i.e. `===`.
  1140. *
  1141. * @static
  1142. * @memberOf _
  1143. * @category Arrays
  1144. * @param {Array} array The array to process.
  1145. * @param {Array} [array1, array2, ...] Arrays to check.
  1146. * @returns {Array} Returns a new array of `array` values not present in the
  1147. * other arrays.
  1148. * @example
  1149. *
  1150. * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
  1151. * // => [1, 3, 4]
  1152. */
  1153. function difference(array) {
  1154. var result = [];
  1155. if (!array) {
  1156. return result;
  1157. }
  1158. var index = -1,
  1159. length = array.length,
  1160. flattened = concat.apply(result, arguments),
  1161. contains = cachedContains(flattened, length);
  1162. while (++index < length) {
  1163. if (!contains(array[index])) {
  1164. result.push(array[index]);
  1165. }
  1166. }
  1167. return result;
  1168. }
  1169. /**
  1170. * Gets the first value of the `array`. Pass `n` to return the first `n` values
  1171. * of the `array`.
  1172. *
  1173. * @static
  1174. * @memberOf _
  1175. * @alias head, take
  1176. * @category Arrays
  1177. * @param {Array} array The array to query.
  1178. * @param {Number} [n] The number of elements to return.
  1179. * @param {Object} [guard] Internally used to allow this method to work with
  1180. * others like `_.map` without using their callback `index` argument for `n`.
  1181. * @returns {Mixed} Returns the first value or an array of the first `n` values
  1182. * of `array`.
  1183. * @example
  1184. *
  1185. * _.first([5, 4, 3, 2, 1]);
  1186. * // => 5
  1187. */
  1188. function first(array, n, guard) {
  1189. if (array) {
  1190. return (n == null || guard) ? array[0] : slice.call(array, 0, n);
  1191. }
  1192. }
  1193. /**
  1194. * Flattens a nested array (the nesting can be to any depth). If `shallow` is
  1195. * truthy, `array` will only be flattened a single level.
  1196. *
  1197. * @static
  1198. * @memberOf _
  1199. * @category Arrays
  1200. * @param {Array} array The array to compact.
  1201. * @param {Boolean} shallow A flag to indicate only flattening a single level.
  1202. * @returns {Array} Returns a new flattened array.
  1203. * @example
  1204. *
  1205. * _.flatten([1, [2], [3, [[4]]]]);
  1206. * // => [1, 2, 3, 4];
  1207. *
  1208. * _.flatten([1, [2], [3, [[4]]]], true);
  1209. * // => [1, 2, 3, [[4]]];
  1210. */
  1211. function flatten(array, shallow) {
  1212. var result = [];
  1213. if (!array) {
  1214. return result;
  1215. }
  1216. var value,
  1217. index = -1,
  1218. length = array.length;
  1219. while (++index < length) {
  1220. value = array[index];
  1221. if (isArray(value)) {
  1222. push.apply(result, shallow ? value : flatten(value));
  1223. } else {
  1224. result.push(value);
  1225. }
  1226. }
  1227. return result;
  1228. }
  1229. /**
  1230. * Gets the index at which the first occurrence of `value` is found using
  1231. * strict equality for comparisons, i.e. `===`. If the `array` is already
  1232. * sorted, passing `true` for `isSorted` will run a faster binary search.
  1233. *
  1234. * @static
  1235. * @memberOf _
  1236. * @category Arrays
  1237. * @param {Array} array The array to search.
  1238. * @param {Mixed} value The value to search for.
  1239. * @param {Boolean|Number} [fromIndex=0] The index to start searching from or
  1240. * `true` to perform a binary search on a sorted `array`.
  1241. * @returns {Number} Returns the index of the matched value or `-1`.
  1242. * @example
  1243. *
  1244. * _.indexOf([1, 2, 3, 1, 2, 3], 2);
  1245. * // => 1
  1246. *
  1247. * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
  1248. * // => 4
  1249. *
  1250. * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
  1251. * // => 2
  1252. */
  1253. function indexOf(array, value, fromIndex) {
  1254. if (!array) {
  1255. return -1;
  1256. }
  1257. var index = -1,
  1258. length = array.length;
  1259. if (fromIndex) {
  1260. if (typeof fromIndex == 'number') {
  1261. index = (fromIndex < 0 ? Math.max(0, length + fromIndex) : fromIndex) - 1;
  1262. } else {
  1263. index = sortedIndex(array, value);
  1264. return array[index] === value ? index : -1;
  1265. }
  1266. }
  1267. while (++index < length) {
  1268. if (array[index] === value) {
  1269. return index;
  1270. }
  1271. }
  1272. return -1;
  1273. }
  1274. /**
  1275. * Gets all but the last value of `array`. Pass `n` to exclude the last `n`
  1276. * values from the result.
  1277. *
  1278. * @static
  1279. * @memberOf _
  1280. * @category Arrays
  1281. * @param {Array} array The array to query.
  1282. * @param {Number} [n] The number of elements to return.
  1283. * @param {Object} [guard] Internally used to allow this method to work with
  1284. * others like `_.map` without using their callback `index` argument for `n`.
  1285. * @returns {Array} Returns all but the last value or `n` values of `array`.
  1286. * @example
  1287. *
  1288. * _.initial([3, 2, 1]);
  1289. * // => [3, 2]
  1290. */
  1291. function initial(array, n, guard) {
  1292. if (!array) {
  1293. return [];
  1294. }
  1295. return slice.call(array, 0, -((n == null || guard) ? 1 : n));
  1296. }
  1297. /**
  1298. * Computes the intersection of all the passed-in arrays.
  1299. *
  1300. * @static
  1301. * @memberOf _
  1302. * @category Arrays
  1303. * @param {Array} [array1, array2, ...] Arrays to process.
  1304. * @returns {Array} Returns a new array of unique values, in order, that are
  1305. * present in **all** of the arrays.
  1306. * @example
  1307. *
  1308. * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
  1309. * // => [1, 2]
  1310. */
  1311. function intersection(array) {
  1312. var result = [];
  1313. if (!array) {
  1314. return result;
  1315. }
  1316. var value,
  1317. index = -1,
  1318. length = array.length,
  1319. others = slice.call(arguments, 1),
  1320. cache = [];
  1321. while (++index < length) {
  1322. value = array[index];
  1323. if (indexOf(result, value) < 0 &&
  1324. every(others, function(other, index) {
  1325. return (cache[index] || (cache[index] = cachedContains(other)))(value);
  1326. })) {
  1327. result.push(value);
  1328. }
  1329. }
  1330. return result;
  1331. }
  1332. /**
  1333. * Gets the last value of the `array`. Pass `n` to return the lasy `n` values
  1334. * of the `array`.
  1335. *
  1336. * @static
  1337. * @memberOf _
  1338. * @category Arrays
  1339. * @param {Array} array The array to query.
  1340. * @param {Number} [n] The number of elements to return.
  1341. * @param {Object} [guard] Internally used to allow this method to work with
  1342. * others like `_.map` without using their callback `index` argument for `n`.
  1343. * @returns {Mixed} Returns the last value or an array of the last `n` values
  1344. * of `array`.
  1345. * @example
  1346. *
  1347. * _.last([3, 2, 1]);
  1348. * // => 1
  1349. */
  1350. function last(array, n, guard) {
  1351. if (array) {
  1352. var length = array.length;
  1353. return (n == null || guard) ? array[length - 1] : slice.call(array, -n || length);
  1354. }
  1355. }
  1356. /**
  1357. * Gets the index at which the last occurrence of `value` is found using
  1358. * strict equality for comparisons, i.e. `===`.
  1359. *
  1360. * @static
  1361. * @memberOf _
  1362. * @category Arrays
  1363. * @param {Array} array The array to search.
  1364. * @param {Mixed} value The value to search for.
  1365. * @param {Number} [fromIndex=array.length-1] The index to start searching from.
  1366. * @returns {Number} Returns the index of the matched value or `-1`.
  1367. * @example
  1368. *
  1369. * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
  1370. * // => 4
  1371. *
  1372. * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
  1373. * // => 1
  1374. */
  1375. function lastIndexOf(array, value, fromIndex) {
  1376. if (!array) {
  1377. return -1;
  1378. }
  1379. var index = array.length;
  1380. if (fromIndex && typeof fromIndex == 'number') {
  1381. index = (fromIndex < 0 ? Math.max(0, index + fromIndex) : Math.min(fromIndex, index - 1)) + 1;
  1382. }
  1383. while (index--) {
  1384. if (array[index] === value) {
  1385. return index;
  1386. }
  1387. }
  1388. return -1;
  1389. }
  1390. /**
  1391. * Retrieves the maximum value of an `array`. If `callback` is passed,
  1392. * it will be executed for each value in the `array` to generate the
  1393. * criterion by which the value is ranked. The `callback` is bound to
  1394. * `thisArg` and invoked with 3 arguments; (value, index, array).
  1395. *
  1396. * @static
  1397. * @memberOf _
  1398. * @category Arrays
  1399. * @param {Array} array The array to iterate over.
  1400. * @param {Function} [callback] The function called per iteration.
  1401. * @param {Mixed} [thisArg] The `this` binding for the callback.
  1402. * @returns {Mixed} Returns the maximum value.
  1403. * @example
  1404. *
  1405. * var stooges = [
  1406. * { 'name': 'moe', 'age': 40 },
  1407. * { 'name': 'larry', 'age': 50 },
  1408. * { 'name': 'curly', 'age': 60 }
  1409. * ];
  1410. *