PageRenderTime 61ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs//0.4.0/lodash.js

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