UNPKG

64.5 kBJavaScriptView Raw
1/**
2 * lodash (Custom Build) <https://lodash.com/>
3 * Build: `lodash modularize exports="npm" -o ./`
4 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
5 * Released under MIT license <https://lodash.com/license>
6 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
7 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
8 */
9
10/** Used as the size to enable large array optimizations. */
11var LARGE_ARRAY_SIZE = 200;
12
13/** Used as the `TypeError` message for "Functions" methods. */
14var FUNC_ERROR_TEXT = 'Expected a function';
15
16/** Used to stand-in for `undefined` hash values. */
17var HASH_UNDEFINED = '__lodash_hash_undefined__';
18
19/** Used to compose bitmasks for comparison styles. */
20var UNORDERED_COMPARE_FLAG = 1,
21 PARTIAL_COMPARE_FLAG = 2;
22
23/** Used as references for various `Number` constants. */
24var INFINITY = 1 / 0,
25 MAX_SAFE_INTEGER = 9007199254740991;
26
27/** `Object#toString` result references. */
28var argsTag = '[object Arguments]',
29 arrayTag = '[object Array]',
30 boolTag = '[object Boolean]',
31 dateTag = '[object Date]',
32 errorTag = '[object Error]',
33 funcTag = '[object Function]',
34 genTag = '[object GeneratorFunction]',
35 mapTag = '[object Map]',
36 numberTag = '[object Number]',
37 objectTag = '[object Object]',
38 promiseTag = '[object Promise]',
39 regexpTag = '[object RegExp]',
40 setTag = '[object Set]',
41 stringTag = '[object String]',
42 symbolTag = '[object Symbol]',
43 weakMapTag = '[object WeakMap]';
44
45var arrayBufferTag = '[object ArrayBuffer]',
46 dataViewTag = '[object DataView]',
47 float32Tag = '[object Float32Array]',
48 float64Tag = '[object Float64Array]',
49 int8Tag = '[object Int8Array]',
50 int16Tag = '[object Int16Array]',
51 int32Tag = '[object Int32Array]',
52 uint8Tag = '[object Uint8Array]',
53 uint8ClampedTag = '[object Uint8ClampedArray]',
54 uint16Tag = '[object Uint16Array]',
55 uint32Tag = '[object Uint32Array]';
56
57/** Used to match property names within property paths. */
58var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
59 reIsPlainProp = /^\w*$/,
60 reLeadingDot = /^\./,
61 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
62
63/**
64 * Used to match `RegExp`
65 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
66 */
67var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
68
69/** Used to match backslashes in property paths. */
70var reEscapeChar = /\\(\\)?/g;
71
72/** Used to detect host constructors (Safari). */
73var reIsHostCtor = /^\[object .+?Constructor\]$/;
74
75/** Used to detect unsigned integer values. */
76var reIsUint = /^(?:0|[1-9]\d*)$/;
77
78/** Used to identify `toStringTag` values of typed arrays. */
79var typedArrayTags = {};
80typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
81typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
82typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
83typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
84typedArrayTags[uint32Tag] = true;
85typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
86typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
87typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
88typedArrayTags[errorTag] = typedArrayTags[funcTag] =
89typedArrayTags[mapTag] = typedArrayTags[numberTag] =
90typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
91typedArrayTags[setTag] = typedArrayTags[stringTag] =
92typedArrayTags[weakMapTag] = false;
93
94/** Detect free variable `global` from Node.js. */
95var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
96
97/** Detect free variable `self`. */
98var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
99
100/** Used as a reference to the global object. */
101var root = freeGlobal || freeSelf || Function('return this')();
102
103/** Detect free variable `exports`. */
104var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
105
106/** Detect free variable `module`. */
107var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
108
109/** Detect the popular CommonJS extension `module.exports`. */
110var moduleExports = freeModule && freeModule.exports === freeExports;
111
112/** Detect free variable `process` from Node.js. */
113var freeProcess = moduleExports && freeGlobal.process;
114
115/** Used to access faster Node.js helpers. */
116var nodeUtil = (function() {
117 try {
118 return freeProcess && freeProcess.binding('util');
119 } catch (e) {}
120}());
121
122/* Node.js helper references. */
123var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
124
125/**
126 * A specialized version of `baseAggregator` for arrays.
127 *
128 * @private
129 * @param {Array} [array] The array to iterate over.
130 * @param {Function} setter The function to set `accumulator` values.
131 * @param {Function} iteratee The iteratee to transform keys.
132 * @param {Object} accumulator The initial aggregated object.
133 * @returns {Function} Returns `accumulator`.
134 */
135function arrayAggregator(array, setter, iteratee, accumulator) {
136 var index = -1,
137 length = array ? array.length : 0;
138
139 while (++index < length) {
140 var value = array[index];
141 setter(accumulator, value, iteratee(value), array);
142 }
143 return accumulator;
144}
145
146/**
147 * A specialized version of `_.some` for arrays without support for iteratee
148 * shorthands.
149 *
150 * @private
151 * @param {Array} [array] The array to iterate over.
152 * @param {Function} predicate The function invoked per iteration.
153 * @returns {boolean} Returns `true` if any element passes the predicate check,
154 * else `false`.
155 */
156function arraySome(array, predicate) {
157 var index = -1,
158 length = array ? array.length : 0;
159
160 while (++index < length) {
161 if (predicate(array[index], index, array)) {
162 return true;
163 }
164 }
165 return false;
166}
167
168/**
169 * The base implementation of `_.property` without support for deep paths.
170 *
171 * @private
172 * @param {string} key The key of the property to get.
173 * @returns {Function} Returns the new accessor function.
174 */
175function baseProperty(key) {
176 return function(object) {
177 return object == null ? undefined : object[key];
178 };
179}
180
181/**
182 * The base implementation of `_.times` without support for iteratee shorthands
183 * or max array length checks.
184 *
185 * @private
186 * @param {number} n The number of times to invoke `iteratee`.
187 * @param {Function} iteratee The function invoked per iteration.
188 * @returns {Array} Returns the array of results.
189 */
190function baseTimes(n, iteratee) {
191 var index = -1,
192 result = Array(n);
193
194 while (++index < n) {
195 result[index] = iteratee(index);
196 }
197 return result;
198}
199
200/**
201 * The base implementation of `_.unary` without support for storing metadata.
202 *
203 * @private
204 * @param {Function} func The function to cap arguments for.
205 * @returns {Function} Returns the new capped function.
206 */
207function baseUnary(func) {
208 return function(value) {
209 return func(value);
210 };
211}
212
213/**
214 * Gets the value at `key` of `object`.
215 *
216 * @private
217 * @param {Object} [object] The object to query.
218 * @param {string} key The key of the property to get.
219 * @returns {*} Returns the property value.
220 */
221function getValue(object, key) {
222 return object == null ? undefined : object[key];
223}
224
225/**
226 * Checks if `value` is a host object in IE < 9.
227 *
228 * @private
229 * @param {*} value The value to check.
230 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
231 */
232function isHostObject(value) {
233 // Many host objects are `Object` objects that can coerce to strings
234 // despite having improperly defined `toString` methods.
235 var result = false;
236 if (value != null && typeof value.toString != 'function') {
237 try {
238 result = !!(value + '');
239 } catch (e) {}
240 }
241 return result;
242}
243
244/**
245 * Converts `map` to its key-value pairs.
246 *
247 * @private
248 * @param {Object} map The map to convert.
249 * @returns {Array} Returns the key-value pairs.
250 */
251function mapToArray(map) {
252 var index = -1,
253 result = Array(map.size);
254
255 map.forEach(function(value, key) {
256 result[++index] = [key, value];
257 });
258 return result;
259}
260
261/**
262 * Creates a unary function that invokes `func` with its argument transformed.
263 *
264 * @private
265 * @param {Function} func The function to wrap.
266 * @param {Function} transform The argument transform.
267 * @returns {Function} Returns the new function.
268 */
269function overArg(func, transform) {
270 return function(arg) {
271 return func(transform(arg));
272 };
273}
274
275/**
276 * Converts `set` to an array of its values.
277 *
278 * @private
279 * @param {Object} set The set to convert.
280 * @returns {Array} Returns the values.
281 */
282function setToArray(set) {
283 var index = -1,
284 result = Array(set.size);
285
286 set.forEach(function(value) {
287 result[++index] = value;
288 });
289 return result;
290}
291
292/** Used for built-in method references. */
293var arrayProto = Array.prototype,
294 funcProto = Function.prototype,
295 objectProto = Object.prototype;
296
297/** Used to detect overreaching core-js shims. */
298var coreJsData = root['__core-js_shared__'];
299
300/** Used to detect methods masquerading as native. */
301var maskSrcKey = (function() {
302 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
303 return uid ? ('Symbol(src)_1.' + uid) : '';
304}());
305
306/** Used to resolve the decompiled source of functions. */
307var funcToString = funcProto.toString;
308
309/** Used to check objects for own properties. */
310var hasOwnProperty = objectProto.hasOwnProperty;
311
312/**
313 * Used to resolve the
314 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
315 * of values.
316 */
317var objectToString = objectProto.toString;
318
319/** Used to detect if a method is native. */
320var reIsNative = RegExp('^' +
321 funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
322 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
323);
324
325/** Built-in value references. */
326var Symbol = root.Symbol,
327 Uint8Array = root.Uint8Array,
328 propertyIsEnumerable = objectProto.propertyIsEnumerable,
329 splice = arrayProto.splice;
330
331/* Built-in method references for those with the same name as other `lodash` methods. */
332var nativeKeys = overArg(Object.keys, Object);
333
334/* Built-in method references that are verified to be native. */
335var DataView = getNative(root, 'DataView'),
336 Map = getNative(root, 'Map'),
337 Promise = getNative(root, 'Promise'),
338 Set = getNative(root, 'Set'),
339 WeakMap = getNative(root, 'WeakMap'),
340 nativeCreate = getNative(Object, 'create');
341
342/** Used to detect maps, sets, and weakmaps. */
343var dataViewCtorString = toSource(DataView),
344 mapCtorString = toSource(Map),
345 promiseCtorString = toSource(Promise),
346 setCtorString = toSource(Set),
347 weakMapCtorString = toSource(WeakMap);
348
349/** Used to convert symbols to primitives and strings. */
350var symbolProto = Symbol ? Symbol.prototype : undefined,
351 symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
352 symbolToString = symbolProto ? symbolProto.toString : undefined;
353
354/**
355 * Creates a hash object.
356 *
357 * @private
358 * @constructor
359 * @param {Array} [entries] The key-value pairs to cache.
360 */
361function Hash(entries) {
362 var index = -1,
363 length = entries ? entries.length : 0;
364
365 this.clear();
366 while (++index < length) {
367 var entry = entries[index];
368 this.set(entry[0], entry[1]);
369 }
370}
371
372/**
373 * Removes all key-value entries from the hash.
374 *
375 * @private
376 * @name clear
377 * @memberOf Hash
378 */
379function hashClear() {
380 this.__data__ = nativeCreate ? nativeCreate(null) : {};
381}
382
383/**
384 * Removes `key` and its value from the hash.
385 *
386 * @private
387 * @name delete
388 * @memberOf Hash
389 * @param {Object} hash The hash to modify.
390 * @param {string} key The key of the value to remove.
391 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
392 */
393function hashDelete(key) {
394 return this.has(key) && delete this.__data__[key];
395}
396
397/**
398 * Gets the hash value for `key`.
399 *
400 * @private
401 * @name get
402 * @memberOf Hash
403 * @param {string} key The key of the value to get.
404 * @returns {*} Returns the entry value.
405 */
406function hashGet(key) {
407 var data = this.__data__;
408 if (nativeCreate) {
409 var result = data[key];
410 return result === HASH_UNDEFINED ? undefined : result;
411 }
412 return hasOwnProperty.call(data, key) ? data[key] : undefined;
413}
414
415/**
416 * Checks if a hash value for `key` exists.
417 *
418 * @private
419 * @name has
420 * @memberOf Hash
421 * @param {string} key The key of the entry to check.
422 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
423 */
424function hashHas(key) {
425 var data = this.__data__;
426 return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
427}
428
429/**
430 * Sets the hash `key` to `value`.
431 *
432 * @private
433 * @name set
434 * @memberOf Hash
435 * @param {string} key The key of the value to set.
436 * @param {*} value The value to set.
437 * @returns {Object} Returns the hash instance.
438 */
439function hashSet(key, value) {
440 var data = this.__data__;
441 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
442 return this;
443}
444
445// Add methods to `Hash`.
446Hash.prototype.clear = hashClear;
447Hash.prototype['delete'] = hashDelete;
448Hash.prototype.get = hashGet;
449Hash.prototype.has = hashHas;
450Hash.prototype.set = hashSet;
451
452/**
453 * Creates an list cache object.
454 *
455 * @private
456 * @constructor
457 * @param {Array} [entries] The key-value pairs to cache.
458 */
459function ListCache(entries) {
460 var index = -1,
461 length = entries ? entries.length : 0;
462
463 this.clear();
464 while (++index < length) {
465 var entry = entries[index];
466 this.set(entry[0], entry[1]);
467 }
468}
469
470/**
471 * Removes all key-value entries from the list cache.
472 *
473 * @private
474 * @name clear
475 * @memberOf ListCache
476 */
477function listCacheClear() {
478 this.__data__ = [];
479}
480
481/**
482 * Removes `key` and its value from the list cache.
483 *
484 * @private
485 * @name delete
486 * @memberOf ListCache
487 * @param {string} key The key of the value to remove.
488 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
489 */
490function listCacheDelete(key) {
491 var data = this.__data__,
492 index = assocIndexOf(data, key);
493
494 if (index < 0) {
495 return false;
496 }
497 var lastIndex = data.length - 1;
498 if (index == lastIndex) {
499 data.pop();
500 } else {
501 splice.call(data, index, 1);
502 }
503 return true;
504}
505
506/**
507 * Gets the list cache value for `key`.
508 *
509 * @private
510 * @name get
511 * @memberOf ListCache
512 * @param {string} key The key of the value to get.
513 * @returns {*} Returns the entry value.
514 */
515function listCacheGet(key) {
516 var data = this.__data__,
517 index = assocIndexOf(data, key);
518
519 return index < 0 ? undefined : data[index][1];
520}
521
522/**
523 * Checks if a list cache value for `key` exists.
524 *
525 * @private
526 * @name has
527 * @memberOf ListCache
528 * @param {string} key The key of the entry to check.
529 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
530 */
531function listCacheHas(key) {
532 return assocIndexOf(this.__data__, key) > -1;
533}
534
535/**
536 * Sets the list cache `key` to `value`.
537 *
538 * @private
539 * @name set
540 * @memberOf ListCache
541 * @param {string} key The key of the value to set.
542 * @param {*} value The value to set.
543 * @returns {Object} Returns the list cache instance.
544 */
545function listCacheSet(key, value) {
546 var data = this.__data__,
547 index = assocIndexOf(data, key);
548
549 if (index < 0) {
550 data.push([key, value]);
551 } else {
552 data[index][1] = value;
553 }
554 return this;
555}
556
557// Add methods to `ListCache`.
558ListCache.prototype.clear = listCacheClear;
559ListCache.prototype['delete'] = listCacheDelete;
560ListCache.prototype.get = listCacheGet;
561ListCache.prototype.has = listCacheHas;
562ListCache.prototype.set = listCacheSet;
563
564/**
565 * Creates a map cache object to store key-value pairs.
566 *
567 * @private
568 * @constructor
569 * @param {Array} [entries] The key-value pairs to cache.
570 */
571function MapCache(entries) {
572 var index = -1,
573 length = entries ? entries.length : 0;
574
575 this.clear();
576 while (++index < length) {
577 var entry = entries[index];
578 this.set(entry[0], entry[1]);
579 }
580}
581
582/**
583 * Removes all key-value entries from the map.
584 *
585 * @private
586 * @name clear
587 * @memberOf MapCache
588 */
589function mapCacheClear() {
590 this.__data__ = {
591 'hash': new Hash,
592 'map': new (Map || ListCache),
593 'string': new Hash
594 };
595}
596
597/**
598 * Removes `key` and its value from the map.
599 *
600 * @private
601 * @name delete
602 * @memberOf MapCache
603 * @param {string} key The key of the value to remove.
604 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
605 */
606function mapCacheDelete(key) {
607 return getMapData(this, key)['delete'](key);
608}
609
610/**
611 * Gets the map value for `key`.
612 *
613 * @private
614 * @name get
615 * @memberOf MapCache
616 * @param {string} key The key of the value to get.
617 * @returns {*} Returns the entry value.
618 */
619function mapCacheGet(key) {
620 return getMapData(this, key).get(key);
621}
622
623/**
624 * Checks if a map value for `key` exists.
625 *
626 * @private
627 * @name has
628 * @memberOf MapCache
629 * @param {string} key The key of the entry to check.
630 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
631 */
632function mapCacheHas(key) {
633 return getMapData(this, key).has(key);
634}
635
636/**
637 * Sets the map `key` to `value`.
638 *
639 * @private
640 * @name set
641 * @memberOf MapCache
642 * @param {string} key The key of the value to set.
643 * @param {*} value The value to set.
644 * @returns {Object} Returns the map cache instance.
645 */
646function mapCacheSet(key, value) {
647 getMapData(this, key).set(key, value);
648 return this;
649}
650
651// Add methods to `MapCache`.
652MapCache.prototype.clear = mapCacheClear;
653MapCache.prototype['delete'] = mapCacheDelete;
654MapCache.prototype.get = mapCacheGet;
655MapCache.prototype.has = mapCacheHas;
656MapCache.prototype.set = mapCacheSet;
657
658/**
659 *
660 * Creates an array cache object to store unique values.
661 *
662 * @private
663 * @constructor
664 * @param {Array} [values] The values to cache.
665 */
666function SetCache(values) {
667 var index = -1,
668 length = values ? values.length : 0;
669
670 this.__data__ = new MapCache;
671 while (++index < length) {
672 this.add(values[index]);
673 }
674}
675
676/**
677 * Adds `value` to the array cache.
678 *
679 * @private
680 * @name add
681 * @memberOf SetCache
682 * @alias push
683 * @param {*} value The value to cache.
684 * @returns {Object} Returns the cache instance.
685 */
686function setCacheAdd(value) {
687 this.__data__.set(value, HASH_UNDEFINED);
688 return this;
689}
690
691/**
692 * Checks if `value` is in the array cache.
693 *
694 * @private
695 * @name has
696 * @memberOf SetCache
697 * @param {*} value The value to search for.
698 * @returns {number} Returns `true` if `value` is found, else `false`.
699 */
700function setCacheHas(value) {
701 return this.__data__.has(value);
702}
703
704// Add methods to `SetCache`.
705SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
706SetCache.prototype.has = setCacheHas;
707
708/**
709 * Creates a stack cache object to store key-value pairs.
710 *
711 * @private
712 * @constructor
713 * @param {Array} [entries] The key-value pairs to cache.
714 */
715function Stack(entries) {
716 this.__data__ = new ListCache(entries);
717}
718
719/**
720 * Removes all key-value entries from the stack.
721 *
722 * @private
723 * @name clear
724 * @memberOf Stack
725 */
726function stackClear() {
727 this.__data__ = new ListCache;
728}
729
730/**
731 * Removes `key` and its value from the stack.
732 *
733 * @private
734 * @name delete
735 * @memberOf Stack
736 * @param {string} key The key of the value to remove.
737 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
738 */
739function stackDelete(key) {
740 return this.__data__['delete'](key);
741}
742
743/**
744 * Gets the stack value for `key`.
745 *
746 * @private
747 * @name get
748 * @memberOf Stack
749 * @param {string} key The key of the value to get.
750 * @returns {*} Returns the entry value.
751 */
752function stackGet(key) {
753 return this.__data__.get(key);
754}
755
756/**
757 * Checks if a stack value for `key` exists.
758 *
759 * @private
760 * @name has
761 * @memberOf Stack
762 * @param {string} key The key of the entry to check.
763 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
764 */
765function stackHas(key) {
766 return this.__data__.has(key);
767}
768
769/**
770 * Sets the stack `key` to `value`.
771 *
772 * @private
773 * @name set
774 * @memberOf Stack
775 * @param {string} key The key of the value to set.
776 * @param {*} value The value to set.
777 * @returns {Object} Returns the stack cache instance.
778 */
779function stackSet(key, value) {
780 var cache = this.__data__;
781 if (cache instanceof ListCache) {
782 var pairs = cache.__data__;
783 if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
784 pairs.push([key, value]);
785 return this;
786 }
787 cache = this.__data__ = new MapCache(pairs);
788 }
789 cache.set(key, value);
790 return this;
791}
792
793// Add methods to `Stack`.
794Stack.prototype.clear = stackClear;
795Stack.prototype['delete'] = stackDelete;
796Stack.prototype.get = stackGet;
797Stack.prototype.has = stackHas;
798Stack.prototype.set = stackSet;
799
800/**
801 * Creates an array of the enumerable property names of the array-like `value`.
802 *
803 * @private
804 * @param {*} value The value to query.
805 * @param {boolean} inherited Specify returning inherited property names.
806 * @returns {Array} Returns the array of property names.
807 */
808function arrayLikeKeys(value, inherited) {
809 // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
810 // Safari 9 makes `arguments.length` enumerable in strict mode.
811 var result = (isArray(value) || isArguments(value))
812 ? baseTimes(value.length, String)
813 : [];
814
815 var length = result.length,
816 skipIndexes = !!length;
817
818 for (var key in value) {
819 if ((inherited || hasOwnProperty.call(value, key)) &&
820 !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
821 result.push(key);
822 }
823 }
824 return result;
825}
826
827/**
828 * Gets the index at which the `key` is found in `array` of key-value pairs.
829 *
830 * @private
831 * @param {Array} array The array to inspect.
832 * @param {*} key The key to search for.
833 * @returns {number} Returns the index of the matched value, else `-1`.
834 */
835function assocIndexOf(array, key) {
836 var length = array.length;
837 while (length--) {
838 if (eq(array[length][0], key)) {
839 return length;
840 }
841 }
842 return -1;
843}
844
845/**
846 * Aggregates elements of `collection` on `accumulator` with keys transformed
847 * by `iteratee` and values set by `setter`.
848 *
849 * @private
850 * @param {Array|Object} collection The collection to iterate over.
851 * @param {Function} setter The function to set `accumulator` values.
852 * @param {Function} iteratee The iteratee to transform keys.
853 * @param {Object} accumulator The initial aggregated object.
854 * @returns {Function} Returns `accumulator`.
855 */
856function baseAggregator(collection, setter, iteratee, accumulator) {
857 baseEach(collection, function(value, key, collection) {
858 setter(accumulator, value, iteratee(value), collection);
859 });
860 return accumulator;
861}
862
863/**
864 * The base implementation of `_.forEach` without support for iteratee shorthands.
865 *
866 * @private
867 * @param {Array|Object} collection The collection to iterate over.
868 * @param {Function} iteratee The function invoked per iteration.
869 * @returns {Array|Object} Returns `collection`.
870 */
871var baseEach = createBaseEach(baseForOwn);
872
873/**
874 * The base implementation of `baseForOwn` which iterates over `object`
875 * properties returned by `keysFunc` and invokes `iteratee` for each property.
876 * Iteratee functions may exit iteration early by explicitly returning `false`.
877 *
878 * @private
879 * @param {Object} object The object to iterate over.
880 * @param {Function} iteratee The function invoked per iteration.
881 * @param {Function} keysFunc The function to get the keys of `object`.
882 * @returns {Object} Returns `object`.
883 */
884var baseFor = createBaseFor();
885
886/**
887 * The base implementation of `_.forOwn` without support for iteratee shorthands.
888 *
889 * @private
890 * @param {Object} object The object to iterate over.
891 * @param {Function} iteratee The function invoked per iteration.
892 * @returns {Object} Returns `object`.
893 */
894function baseForOwn(object, iteratee) {
895 return object && baseFor(object, iteratee, keys);
896}
897
898/**
899 * The base implementation of `_.get` without support for default values.
900 *
901 * @private
902 * @param {Object} object The object to query.
903 * @param {Array|string} path The path of the property to get.
904 * @returns {*} Returns the resolved value.
905 */
906function baseGet(object, path) {
907 path = isKey(path, object) ? [path] : castPath(path);
908
909 var index = 0,
910 length = path.length;
911
912 while (object != null && index < length) {
913 object = object[toKey(path[index++])];
914 }
915 return (index && index == length) ? object : undefined;
916}
917
918/**
919 * The base implementation of `getTag`.
920 *
921 * @private
922 * @param {*} value The value to query.
923 * @returns {string} Returns the `toStringTag`.
924 */
925function baseGetTag(value) {
926 return objectToString.call(value);
927}
928
929/**
930 * The base implementation of `_.hasIn` without support for deep paths.
931 *
932 * @private
933 * @param {Object} [object] The object to query.
934 * @param {Array|string} key The key to check.
935 * @returns {boolean} Returns `true` if `key` exists, else `false`.
936 */
937function baseHasIn(object, key) {
938 return object != null && key in Object(object);
939}
940
941/**
942 * The base implementation of `_.isEqual` which supports partial comparisons
943 * and tracks traversed objects.
944 *
945 * @private
946 * @param {*} value The value to compare.
947 * @param {*} other The other value to compare.
948 * @param {Function} [customizer] The function to customize comparisons.
949 * @param {boolean} [bitmask] The bitmask of comparison flags.
950 * The bitmask may be composed of the following flags:
951 * 1 - Unordered comparison
952 * 2 - Partial comparison
953 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
954 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
955 */
956function baseIsEqual(value, other, customizer, bitmask, stack) {
957 if (value === other) {
958 return true;
959 }
960 if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
961 return value !== value && other !== other;
962 }
963 return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
964}
965
966/**
967 * A specialized version of `baseIsEqual` for arrays and objects which performs
968 * deep comparisons and tracks traversed objects enabling objects with circular
969 * references to be compared.
970 *
971 * @private
972 * @param {Object} object The object to compare.
973 * @param {Object} other The other object to compare.
974 * @param {Function} equalFunc The function to determine equivalents of values.
975 * @param {Function} [customizer] The function to customize comparisons.
976 * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
977 * for more details.
978 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
979 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
980 */
981function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
982 var objIsArr = isArray(object),
983 othIsArr = isArray(other),
984 objTag = arrayTag,
985 othTag = arrayTag;
986
987 if (!objIsArr) {
988 objTag = getTag(object);
989 objTag = objTag == argsTag ? objectTag : objTag;
990 }
991 if (!othIsArr) {
992 othTag = getTag(other);
993 othTag = othTag == argsTag ? objectTag : othTag;
994 }
995 var objIsObj = objTag == objectTag && !isHostObject(object),
996 othIsObj = othTag == objectTag && !isHostObject(other),
997 isSameTag = objTag == othTag;
998
999 if (isSameTag && !objIsObj) {
1000 stack || (stack = new Stack);
1001 return (objIsArr || isTypedArray(object))
1002 ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
1003 : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
1004 }
1005 if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
1006 var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
1007 othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
1008
1009 if (objIsWrapped || othIsWrapped) {
1010 var objUnwrapped = objIsWrapped ? object.value() : object,
1011 othUnwrapped = othIsWrapped ? other.value() : other;
1012
1013 stack || (stack = new Stack);
1014 return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
1015 }
1016 }
1017 if (!isSameTag) {
1018 return false;
1019 }
1020 stack || (stack = new Stack);
1021 return equalObjects(object, other, equalFunc, customizer, bitmask, stack);
1022}
1023
1024/**
1025 * The base implementation of `_.isMatch` without support for iteratee shorthands.
1026 *
1027 * @private
1028 * @param {Object} object The object to inspect.
1029 * @param {Object} source The object of property values to match.
1030 * @param {Array} matchData The property names, values, and compare flags to match.
1031 * @param {Function} [customizer] The function to customize comparisons.
1032 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
1033 */
1034function baseIsMatch(object, source, matchData, customizer) {
1035 var index = matchData.length,
1036 length = index,
1037 noCustomizer = !customizer;
1038
1039 if (object == null) {
1040 return !length;
1041 }
1042 object = Object(object);
1043 while (index--) {
1044 var data = matchData[index];
1045 if ((noCustomizer && data[2])
1046 ? data[1] !== object[data[0]]
1047 : !(data[0] in object)
1048 ) {
1049 return false;
1050 }
1051 }
1052 while (++index < length) {
1053 data = matchData[index];
1054 var key = data[0],
1055 objValue = object[key],
1056 srcValue = data[1];
1057
1058 if (noCustomizer && data[2]) {
1059 if (objValue === undefined && !(key in object)) {
1060 return false;
1061 }
1062 } else {
1063 var stack = new Stack;
1064 if (customizer) {
1065 var result = customizer(objValue, srcValue, key, object, source, stack);
1066 }
1067 if (!(result === undefined
1068 ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
1069 : result
1070 )) {
1071 return false;
1072 }
1073 }
1074 }
1075 return true;
1076}
1077
1078/**
1079 * The base implementation of `_.isNative` without bad shim checks.
1080 *
1081 * @private
1082 * @param {*} value The value to check.
1083 * @returns {boolean} Returns `true` if `value` is a native function,
1084 * else `false`.
1085 */
1086function baseIsNative(value) {
1087 if (!isObject(value) || isMasked(value)) {
1088 return false;
1089 }
1090 var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
1091 return pattern.test(toSource(value));
1092}
1093
1094/**
1095 * The base implementation of `_.isTypedArray` without Node.js optimizations.
1096 *
1097 * @private
1098 * @param {*} value The value to check.
1099 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
1100 */
1101function baseIsTypedArray(value) {
1102 return isObjectLike(value) &&
1103 isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
1104}
1105
1106/**
1107 * The base implementation of `_.iteratee`.
1108 *
1109 * @private
1110 * @param {*} [value=_.identity] The value to convert to an iteratee.
1111 * @returns {Function} Returns the iteratee.
1112 */
1113function baseIteratee(value) {
1114 // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
1115 // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
1116 if (typeof value == 'function') {
1117 return value;
1118 }
1119 if (value == null) {
1120 return identity;
1121 }
1122 if (typeof value == 'object') {
1123 return isArray(value)
1124 ? baseMatchesProperty(value[0], value[1])
1125 : baseMatches(value);
1126 }
1127 return property(value);
1128}
1129
1130/**
1131 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
1132 *
1133 * @private
1134 * @param {Object} object The object to query.
1135 * @returns {Array} Returns the array of property names.
1136 */
1137function baseKeys(object) {
1138 if (!isPrototype(object)) {
1139 return nativeKeys(object);
1140 }
1141 var result = [];
1142 for (var key in Object(object)) {
1143 if (hasOwnProperty.call(object, key) && key != 'constructor') {
1144 result.push(key);
1145 }
1146 }
1147 return result;
1148}
1149
1150/**
1151 * The base implementation of `_.matches` which doesn't clone `source`.
1152 *
1153 * @private
1154 * @param {Object} source The object of property values to match.
1155 * @returns {Function} Returns the new spec function.
1156 */
1157function baseMatches(source) {
1158 var matchData = getMatchData(source);
1159 if (matchData.length == 1 && matchData[0][2]) {
1160 return matchesStrictComparable(matchData[0][0], matchData[0][1]);
1161 }
1162 return function(object) {
1163 return object === source || baseIsMatch(object, source, matchData);
1164 };
1165}
1166
1167/**
1168 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
1169 *
1170 * @private
1171 * @param {string} path The path of the property to get.
1172 * @param {*} srcValue The value to match.
1173 * @returns {Function} Returns the new spec function.
1174 */
1175function baseMatchesProperty(path, srcValue) {
1176 if (isKey(path) && isStrictComparable(srcValue)) {
1177 return matchesStrictComparable(toKey(path), srcValue);
1178 }
1179 return function(object) {
1180 var objValue = get(object, path);
1181 return (objValue === undefined && objValue === srcValue)
1182 ? hasIn(object, path)
1183 : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
1184 };
1185}
1186
1187/**
1188 * A specialized version of `baseProperty` which supports deep paths.
1189 *
1190 * @private
1191 * @param {Array|string} path The path of the property to get.
1192 * @returns {Function} Returns the new accessor function.
1193 */
1194function basePropertyDeep(path) {
1195 return function(object) {
1196 return baseGet(object, path);
1197 };
1198}
1199
1200/**
1201 * The base implementation of `_.toString` which doesn't convert nullish
1202 * values to empty strings.
1203 *
1204 * @private
1205 * @param {*} value The value to process.
1206 * @returns {string} Returns the string.
1207 */
1208function baseToString(value) {
1209 // Exit early for strings to avoid a performance hit in some environments.
1210 if (typeof value == 'string') {
1211 return value;
1212 }
1213 if (isSymbol(value)) {
1214 return symbolToString ? symbolToString.call(value) : '';
1215 }
1216 var result = (value + '');
1217 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
1218}
1219
1220/**
1221 * Casts `value` to a path array if it's not one.
1222 *
1223 * @private
1224 * @param {*} value The value to inspect.
1225 * @returns {Array} Returns the cast property path array.
1226 */
1227function castPath(value) {
1228 return isArray(value) ? value : stringToPath(value);
1229}
1230
1231/**
1232 * Creates a function like `_.groupBy`.
1233 *
1234 * @private
1235 * @param {Function} setter The function to set accumulator values.
1236 * @param {Function} [initializer] The accumulator object initializer.
1237 * @returns {Function} Returns the new aggregator function.
1238 */
1239function createAggregator(setter, initializer) {
1240 return function(collection, iteratee) {
1241 var func = isArray(collection) ? arrayAggregator : baseAggregator,
1242 accumulator = initializer ? initializer() : {};
1243
1244 return func(collection, setter, baseIteratee(iteratee, 2), accumulator);
1245 };
1246}
1247
1248/**
1249 * Creates a `baseEach` or `baseEachRight` function.
1250 *
1251 * @private
1252 * @param {Function} eachFunc The function to iterate over a collection.
1253 * @param {boolean} [fromRight] Specify iterating from right to left.
1254 * @returns {Function} Returns the new base function.
1255 */
1256function createBaseEach(eachFunc, fromRight) {
1257 return function(collection, iteratee) {
1258 if (collection == null) {
1259 return collection;
1260 }
1261 if (!isArrayLike(collection)) {
1262 return eachFunc(collection, iteratee);
1263 }
1264 var length = collection.length,
1265 index = fromRight ? length : -1,
1266 iterable = Object(collection);
1267
1268 while ((fromRight ? index-- : ++index < length)) {
1269 if (iteratee(iterable[index], index, iterable) === false) {
1270 break;
1271 }
1272 }
1273 return collection;
1274 };
1275}
1276
1277/**
1278 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
1279 *
1280 * @private
1281 * @param {boolean} [fromRight] Specify iterating from right to left.
1282 * @returns {Function} Returns the new base function.
1283 */
1284function createBaseFor(fromRight) {
1285 return function(object, iteratee, keysFunc) {
1286 var index = -1,
1287 iterable = Object(object),
1288 props = keysFunc(object),
1289 length = props.length;
1290
1291 while (length--) {
1292 var key = props[fromRight ? length : ++index];
1293 if (iteratee(iterable[key], key, iterable) === false) {
1294 break;
1295 }
1296 }
1297 return object;
1298 };
1299}
1300
1301/**
1302 * A specialized version of `baseIsEqualDeep` for arrays with support for
1303 * partial deep comparisons.
1304 *
1305 * @private
1306 * @param {Array} array The array to compare.
1307 * @param {Array} other The other array to compare.
1308 * @param {Function} equalFunc The function to determine equivalents of values.
1309 * @param {Function} customizer The function to customize comparisons.
1310 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
1311 * for more details.
1312 * @param {Object} stack Tracks traversed `array` and `other` objects.
1313 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
1314 */
1315function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
1316 var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
1317 arrLength = array.length,
1318 othLength = other.length;
1319
1320 if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
1321 return false;
1322 }
1323 // Assume cyclic values are equal.
1324 var stacked = stack.get(array);
1325 if (stacked && stack.get(other)) {
1326 return stacked == other;
1327 }
1328 var index = -1,
1329 result = true,
1330 seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined;
1331
1332 stack.set(array, other);
1333 stack.set(other, array);
1334
1335 // Ignore non-index properties.
1336 while (++index < arrLength) {
1337 var arrValue = array[index],
1338 othValue = other[index];
1339
1340 if (customizer) {
1341 var compared = isPartial
1342 ? customizer(othValue, arrValue, index, other, array, stack)
1343 : customizer(arrValue, othValue, index, array, other, stack);
1344 }
1345 if (compared !== undefined) {
1346 if (compared) {
1347 continue;
1348 }
1349 result = false;
1350 break;
1351 }
1352 // Recursively compare arrays (susceptible to call stack limits).
1353 if (seen) {
1354 if (!arraySome(other, function(othValue, othIndex) {
1355 if (!seen.has(othIndex) &&
1356 (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
1357 return seen.add(othIndex);
1358 }
1359 })) {
1360 result = false;
1361 break;
1362 }
1363 } else if (!(
1364 arrValue === othValue ||
1365 equalFunc(arrValue, othValue, customizer, bitmask, stack)
1366 )) {
1367 result = false;
1368 break;
1369 }
1370 }
1371 stack['delete'](array);
1372 stack['delete'](other);
1373 return result;
1374}
1375
1376/**
1377 * A specialized version of `baseIsEqualDeep` for comparing objects of
1378 * the same `toStringTag`.
1379 *
1380 * **Note:** This function only supports comparing values with tags of
1381 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
1382 *
1383 * @private
1384 * @param {Object} object The object to compare.
1385 * @param {Object} other The other object to compare.
1386 * @param {string} tag The `toStringTag` of the objects to compare.
1387 * @param {Function} equalFunc The function to determine equivalents of values.
1388 * @param {Function} customizer The function to customize comparisons.
1389 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
1390 * for more details.
1391 * @param {Object} stack Tracks traversed `object` and `other` objects.
1392 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
1393 */
1394function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {
1395 switch (tag) {
1396 case dataViewTag:
1397 if ((object.byteLength != other.byteLength) ||
1398 (object.byteOffset != other.byteOffset)) {
1399 return false;
1400 }
1401 object = object.buffer;
1402 other = other.buffer;
1403
1404 case arrayBufferTag:
1405 if ((object.byteLength != other.byteLength) ||
1406 !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
1407 return false;
1408 }
1409 return true;
1410
1411 case boolTag:
1412 case dateTag:
1413 case numberTag:
1414 // Coerce booleans to `1` or `0` and dates to milliseconds.
1415 // Invalid dates are coerced to `NaN`.
1416 return eq(+object, +other);
1417
1418 case errorTag:
1419 return object.name == other.name && object.message == other.message;
1420
1421 case regexpTag:
1422 case stringTag:
1423 // Coerce regexes to strings and treat strings, primitives and objects,
1424 // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
1425 // for more details.
1426 return object == (other + '');
1427
1428 case mapTag:
1429 var convert = mapToArray;
1430
1431 case setTag:
1432 var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
1433 convert || (convert = setToArray);
1434
1435 if (object.size != other.size && !isPartial) {
1436 return false;
1437 }
1438 // Assume cyclic values are equal.
1439 var stacked = stack.get(object);
1440 if (stacked) {
1441 return stacked == other;
1442 }
1443 bitmask |= UNORDERED_COMPARE_FLAG;
1444
1445 // Recursively compare objects (susceptible to call stack limits).
1446 stack.set(object, other);
1447 var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);
1448 stack['delete'](object);
1449 return result;
1450
1451 case symbolTag:
1452 if (symbolValueOf) {
1453 return symbolValueOf.call(object) == symbolValueOf.call(other);
1454 }
1455 }
1456 return false;
1457}
1458
1459/**
1460 * A specialized version of `baseIsEqualDeep` for objects with support for
1461 * partial deep comparisons.
1462 *
1463 * @private
1464 * @param {Object} object The object to compare.
1465 * @param {Object} other The other object to compare.
1466 * @param {Function} equalFunc The function to determine equivalents of values.
1467 * @param {Function} customizer The function to customize comparisons.
1468 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
1469 * for more details.
1470 * @param {Object} stack Tracks traversed `object` and `other` objects.
1471 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
1472 */
1473function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
1474 var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
1475 objProps = keys(object),
1476 objLength = objProps.length,
1477 othProps = keys(other),
1478 othLength = othProps.length;
1479
1480 if (objLength != othLength && !isPartial) {
1481 return false;
1482 }
1483 var index = objLength;
1484 while (index--) {
1485 var key = objProps[index];
1486 if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
1487 return false;
1488 }
1489 }
1490 // Assume cyclic values are equal.
1491 var stacked = stack.get(object);
1492 if (stacked && stack.get(other)) {
1493 return stacked == other;
1494 }
1495 var result = true;
1496 stack.set(object, other);
1497 stack.set(other, object);
1498
1499 var skipCtor = isPartial;
1500 while (++index < objLength) {
1501 key = objProps[index];
1502 var objValue = object[key],
1503 othValue = other[key];
1504
1505 if (customizer) {
1506 var compared = isPartial
1507 ? customizer(othValue, objValue, key, other, object, stack)
1508 : customizer(objValue, othValue, key, object, other, stack);
1509 }
1510 // Recursively compare objects (susceptible to call stack limits).
1511 if (!(compared === undefined
1512 ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
1513 : compared
1514 )) {
1515 result = false;
1516 break;
1517 }
1518 skipCtor || (skipCtor = key == 'constructor');
1519 }
1520 if (result && !skipCtor) {
1521 var objCtor = object.constructor,
1522 othCtor = other.constructor;
1523
1524 // Non `Object` object instances with different constructors are not equal.
1525 if (objCtor != othCtor &&
1526 ('constructor' in object && 'constructor' in other) &&
1527 !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
1528 typeof othCtor == 'function' && othCtor instanceof othCtor)) {
1529 result = false;
1530 }
1531 }
1532 stack['delete'](object);
1533 stack['delete'](other);
1534 return result;
1535}
1536
1537/**
1538 * Gets the data for `map`.
1539 *
1540 * @private
1541 * @param {Object} map The map to query.
1542 * @param {string} key The reference key.
1543 * @returns {*} Returns the map data.
1544 */
1545function getMapData(map, key) {
1546 var data = map.__data__;
1547 return isKeyable(key)
1548 ? data[typeof key == 'string' ? 'string' : 'hash']
1549 : data.map;
1550}
1551
1552/**
1553 * Gets the property names, values, and compare flags of `object`.
1554 *
1555 * @private
1556 * @param {Object} object The object to query.
1557 * @returns {Array} Returns the match data of `object`.
1558 */
1559function getMatchData(object) {
1560 var result = keys(object),
1561 length = result.length;
1562
1563 while (length--) {
1564 var key = result[length],
1565 value = object[key];
1566
1567 result[length] = [key, value, isStrictComparable(value)];
1568 }
1569 return result;
1570}
1571
1572/**
1573 * Gets the native function at `key` of `object`.
1574 *
1575 * @private
1576 * @param {Object} object The object to query.
1577 * @param {string} key The key of the method to get.
1578 * @returns {*} Returns the function if it's native, else `undefined`.
1579 */
1580function getNative(object, key) {
1581 var value = getValue(object, key);
1582 return baseIsNative(value) ? value : undefined;
1583}
1584
1585/**
1586 * Gets the `toStringTag` of `value`.
1587 *
1588 * @private
1589 * @param {*} value The value to query.
1590 * @returns {string} Returns the `toStringTag`.
1591 */
1592var getTag = baseGetTag;
1593
1594// Fallback for data views, maps, sets, and weak maps in IE 11,
1595// for data views in Edge < 14, and promises in Node.js.
1596if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
1597 (Map && getTag(new Map) != mapTag) ||
1598 (Promise && getTag(Promise.resolve()) != promiseTag) ||
1599 (Set && getTag(new Set) != setTag) ||
1600 (WeakMap && getTag(new WeakMap) != weakMapTag)) {
1601 getTag = function(value) {
1602 var result = objectToString.call(value),
1603 Ctor = result == objectTag ? value.constructor : undefined,
1604 ctorString = Ctor ? toSource(Ctor) : undefined;
1605
1606 if (ctorString) {
1607 switch (ctorString) {
1608 case dataViewCtorString: return dataViewTag;
1609 case mapCtorString: return mapTag;
1610 case promiseCtorString: return promiseTag;
1611 case setCtorString: return setTag;
1612 case weakMapCtorString: return weakMapTag;
1613 }
1614 }
1615 return result;
1616 };
1617}
1618
1619/**
1620 * Checks if `path` exists on `object`.
1621 *
1622 * @private
1623 * @param {Object} object The object to query.
1624 * @param {Array|string} path The path to check.
1625 * @param {Function} hasFunc The function to check properties.
1626 * @returns {boolean} Returns `true` if `path` exists, else `false`.
1627 */
1628function hasPath(object, path, hasFunc) {
1629 path = isKey(path, object) ? [path] : castPath(path);
1630
1631 var result,
1632 index = -1,
1633 length = path.length;
1634
1635 while (++index < length) {
1636 var key = toKey(path[index]);
1637 if (!(result = object != null && hasFunc(object, key))) {
1638 break;
1639 }
1640 object = object[key];
1641 }
1642 if (result) {
1643 return result;
1644 }
1645 var length = object ? object.length : 0;
1646 return !!length && isLength(length) && isIndex(key, length) &&
1647 (isArray(object) || isArguments(object));
1648}
1649
1650/**
1651 * Checks if `value` is a valid array-like index.
1652 *
1653 * @private
1654 * @param {*} value The value to check.
1655 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
1656 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
1657 */
1658function isIndex(value, length) {
1659 length = length == null ? MAX_SAFE_INTEGER : length;
1660 return !!length &&
1661 (typeof value == 'number' || reIsUint.test(value)) &&
1662 (value > -1 && value % 1 == 0 && value < length);
1663}
1664
1665/**
1666 * Checks if `value` is a property name and not a property path.
1667 *
1668 * @private
1669 * @param {*} value The value to check.
1670 * @param {Object} [object] The object to query keys on.
1671 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
1672 */
1673function isKey(value, object) {
1674 if (isArray(value)) {
1675 return false;
1676 }
1677 var type = typeof value;
1678 if (type == 'number' || type == 'symbol' || type == 'boolean' ||
1679 value == null || isSymbol(value)) {
1680 return true;
1681 }
1682 return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
1683 (object != null && value in Object(object));
1684}
1685
1686/**
1687 * Checks if `value` is suitable for use as unique object key.
1688 *
1689 * @private
1690 * @param {*} value The value to check.
1691 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
1692 */
1693function isKeyable(value) {
1694 var type = typeof value;
1695 return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
1696 ? (value !== '__proto__')
1697 : (value === null);
1698}
1699
1700/**
1701 * Checks if `func` has its source masked.
1702 *
1703 * @private
1704 * @param {Function} func The function to check.
1705 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
1706 */
1707function isMasked(func) {
1708 return !!maskSrcKey && (maskSrcKey in func);
1709}
1710
1711/**
1712 * Checks if `value` is likely a prototype object.
1713 *
1714 * @private
1715 * @param {*} value The value to check.
1716 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
1717 */
1718function isPrototype(value) {
1719 var Ctor = value && value.constructor,
1720 proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
1721
1722 return value === proto;
1723}
1724
1725/**
1726 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
1727 *
1728 * @private
1729 * @param {*} value The value to check.
1730 * @returns {boolean} Returns `true` if `value` if suitable for strict
1731 * equality comparisons, else `false`.
1732 */
1733function isStrictComparable(value) {
1734 return value === value && !isObject(value);
1735}
1736
1737/**
1738 * A specialized version of `matchesProperty` for source values suitable
1739 * for strict equality comparisons, i.e. `===`.
1740 *
1741 * @private
1742 * @param {string} key The key of the property to get.
1743 * @param {*} srcValue The value to match.
1744 * @returns {Function} Returns the new spec function.
1745 */
1746function matchesStrictComparable(key, srcValue) {
1747 return function(object) {
1748 if (object == null) {
1749 return false;
1750 }
1751 return object[key] === srcValue &&
1752 (srcValue !== undefined || (key in Object(object)));
1753 };
1754}
1755
1756/**
1757 * Converts `string` to a property path array.
1758 *
1759 * @private
1760 * @param {string} string The string to convert.
1761 * @returns {Array} Returns the property path array.
1762 */
1763var stringToPath = memoize(function(string) {
1764 string = toString(string);
1765
1766 var result = [];
1767 if (reLeadingDot.test(string)) {
1768 result.push('');
1769 }
1770 string.replace(rePropName, function(match, number, quote, string) {
1771 result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
1772 });
1773 return result;
1774});
1775
1776/**
1777 * Converts `value` to a string key if it's not a string or symbol.
1778 *
1779 * @private
1780 * @param {*} value The value to inspect.
1781 * @returns {string|symbol} Returns the key.
1782 */
1783function toKey(value) {
1784 if (typeof value == 'string' || isSymbol(value)) {
1785 return value;
1786 }
1787 var result = (value + '');
1788 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
1789}
1790
1791/**
1792 * Converts `func` to its source code.
1793 *
1794 * @private
1795 * @param {Function} func The function to process.
1796 * @returns {string} Returns the source code.
1797 */
1798function toSource(func) {
1799 if (func != null) {
1800 try {
1801 return funcToString.call(func);
1802 } catch (e) {}
1803 try {
1804 return (func + '');
1805 } catch (e) {}
1806 }
1807 return '';
1808}
1809
1810/**
1811 * Creates an object composed of keys generated from the results of running
1812 * each element of `collection` thru `iteratee`. The corresponding value of
1813 * each key is the last element responsible for generating the key. The
1814 * iteratee is invoked with one argument: (value).
1815 *
1816 * @static
1817 * @memberOf _
1818 * @since 4.0.0
1819 * @category Collection
1820 * @param {Array|Object} collection The collection to iterate over.
1821 * @param {Function} [iteratee=_.identity]
1822 * The iteratee to transform keys.
1823 * @returns {Object} Returns the composed aggregate object.
1824 * @example
1825 *
1826 * var array = [
1827 * { 'dir': 'left', 'code': 97 },
1828 * { 'dir': 'right', 'code': 100 }
1829 * ];
1830 *
1831 * _.keyBy(array, function(o) {
1832 * return String.fromCharCode(o.code);
1833 * });
1834 * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
1835 *
1836 * _.keyBy(array, 'dir');
1837 * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
1838 */
1839var keyBy = createAggregator(function(result, value, key) {
1840 result[key] = value;
1841});
1842
1843/**
1844 * Creates a function that memoizes the result of `func`. If `resolver` is
1845 * provided, it determines the cache key for storing the result based on the
1846 * arguments provided to the memoized function. By default, the first argument
1847 * provided to the memoized function is used as the map cache key. The `func`
1848 * is invoked with the `this` binding of the memoized function.
1849 *
1850 * **Note:** The cache is exposed as the `cache` property on the memoized
1851 * function. Its creation may be customized by replacing the `_.memoize.Cache`
1852 * constructor with one whose instances implement the
1853 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
1854 * method interface of `delete`, `get`, `has`, and `set`.
1855 *
1856 * @static
1857 * @memberOf _
1858 * @since 0.1.0
1859 * @category Function
1860 * @param {Function} func The function to have its output memoized.
1861 * @param {Function} [resolver] The function to resolve the cache key.
1862 * @returns {Function} Returns the new memoized function.
1863 * @example
1864 *
1865 * var object = { 'a': 1, 'b': 2 };
1866 * var other = { 'c': 3, 'd': 4 };
1867 *
1868 * var values = _.memoize(_.values);
1869 * values(object);
1870 * // => [1, 2]
1871 *
1872 * values(other);
1873 * // => [3, 4]
1874 *
1875 * object.a = 2;
1876 * values(object);
1877 * // => [1, 2]
1878 *
1879 * // Modify the result cache.
1880 * values.cache.set(object, ['a', 'b']);
1881 * values(object);
1882 * // => ['a', 'b']
1883 *
1884 * // Replace `_.memoize.Cache`.
1885 * _.memoize.Cache = WeakMap;
1886 */
1887function memoize(func, resolver) {
1888 if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
1889 throw new TypeError(FUNC_ERROR_TEXT);
1890 }
1891 var memoized = function() {
1892 var args = arguments,
1893 key = resolver ? resolver.apply(this, args) : args[0],
1894 cache = memoized.cache;
1895
1896 if (cache.has(key)) {
1897 return cache.get(key);
1898 }
1899 var result = func.apply(this, args);
1900 memoized.cache = cache.set(key, result);
1901 return result;
1902 };
1903 memoized.cache = new (memoize.Cache || MapCache);
1904 return memoized;
1905}
1906
1907// Assign cache to `_.memoize`.
1908memoize.Cache = MapCache;
1909
1910/**
1911 * Performs a
1912 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
1913 * comparison between two values to determine if they are equivalent.
1914 *
1915 * @static
1916 * @memberOf _
1917 * @since 4.0.0
1918 * @category Lang
1919 * @param {*} value The value to compare.
1920 * @param {*} other The other value to compare.
1921 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
1922 * @example
1923 *
1924 * var object = { 'a': 1 };
1925 * var other = { 'a': 1 };
1926 *
1927 * _.eq(object, object);
1928 * // => true
1929 *
1930 * _.eq(object, other);
1931 * // => false
1932 *
1933 * _.eq('a', 'a');
1934 * // => true
1935 *
1936 * _.eq('a', Object('a'));
1937 * // => false
1938 *
1939 * _.eq(NaN, NaN);
1940 * // => true
1941 */
1942function eq(value, other) {
1943 return value === other || (value !== value && other !== other);
1944}
1945
1946/**
1947 * Checks if `value` is likely an `arguments` object.
1948 *
1949 * @static
1950 * @memberOf _
1951 * @since 0.1.0
1952 * @category Lang
1953 * @param {*} value The value to check.
1954 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
1955 * else `false`.
1956 * @example
1957 *
1958 * _.isArguments(function() { return arguments; }());
1959 * // => true
1960 *
1961 * _.isArguments([1, 2, 3]);
1962 * // => false
1963 */
1964function isArguments(value) {
1965 // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
1966 return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
1967 (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
1968}
1969
1970/**
1971 * Checks if `value` is classified as an `Array` object.
1972 *
1973 * @static
1974 * @memberOf _
1975 * @since 0.1.0
1976 * @category Lang
1977 * @param {*} value The value to check.
1978 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
1979 * @example
1980 *
1981 * _.isArray([1, 2, 3]);
1982 * // => true
1983 *
1984 * _.isArray(document.body.children);
1985 * // => false
1986 *
1987 * _.isArray('abc');
1988 * // => false
1989 *
1990 * _.isArray(_.noop);
1991 * // => false
1992 */
1993var isArray = Array.isArray;
1994
1995/**
1996 * Checks if `value` is array-like. A value is considered array-like if it's
1997 * not a function and has a `value.length` that's an integer greater than or
1998 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
1999 *
2000 * @static
2001 * @memberOf _
2002 * @since 4.0.0
2003 * @category Lang
2004 * @param {*} value The value to check.
2005 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
2006 * @example
2007 *
2008 * _.isArrayLike([1, 2, 3]);
2009 * // => true
2010 *
2011 * _.isArrayLike(document.body.children);
2012 * // => true
2013 *
2014 * _.isArrayLike('abc');
2015 * // => true
2016 *
2017 * _.isArrayLike(_.noop);
2018 * // => false
2019 */
2020function isArrayLike(value) {
2021 return value != null && isLength(value.length) && !isFunction(value);
2022}
2023
2024/**
2025 * This method is like `_.isArrayLike` except that it also checks if `value`
2026 * is an object.
2027 *
2028 * @static
2029 * @memberOf _
2030 * @since 4.0.0
2031 * @category Lang
2032 * @param {*} value The value to check.
2033 * @returns {boolean} Returns `true` if `value` is an array-like object,
2034 * else `false`.
2035 * @example
2036 *
2037 * _.isArrayLikeObject([1, 2, 3]);
2038 * // => true
2039 *
2040 * _.isArrayLikeObject(document.body.children);
2041 * // => true
2042 *
2043 * _.isArrayLikeObject('abc');
2044 * // => false
2045 *
2046 * _.isArrayLikeObject(_.noop);
2047 * // => false
2048 */
2049function isArrayLikeObject(value) {
2050 return isObjectLike(value) && isArrayLike(value);
2051}
2052
2053/**
2054 * Checks if `value` is classified as a `Function` object.
2055 *
2056 * @static
2057 * @memberOf _
2058 * @since 0.1.0
2059 * @category Lang
2060 * @param {*} value The value to check.
2061 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
2062 * @example
2063 *
2064 * _.isFunction(_);
2065 * // => true
2066 *
2067 * _.isFunction(/abc/);
2068 * // => false
2069 */
2070function isFunction(value) {
2071 // The use of `Object#toString` avoids issues with the `typeof` operator
2072 // in Safari 8-9 which returns 'object' for typed array and other constructors.
2073 var tag = isObject(value) ? objectToString.call(value) : '';
2074 return tag == funcTag || tag == genTag;
2075}
2076
2077/**
2078 * Checks if `value` is a valid array-like length.
2079 *
2080 * **Note:** This method is loosely based on
2081 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
2082 *
2083 * @static
2084 * @memberOf _
2085 * @since 4.0.0
2086 * @category Lang
2087 * @param {*} value The value to check.
2088 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
2089 * @example
2090 *
2091 * _.isLength(3);
2092 * // => true
2093 *
2094 * _.isLength(Number.MIN_VALUE);
2095 * // => false
2096 *
2097 * _.isLength(Infinity);
2098 * // => false
2099 *
2100 * _.isLength('3');
2101 * // => false
2102 */
2103function isLength(value) {
2104 return typeof value == 'number' &&
2105 value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
2106}
2107
2108/**
2109 * Checks if `value` is the
2110 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
2111 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
2112 *
2113 * @static
2114 * @memberOf _
2115 * @since 0.1.0
2116 * @category Lang
2117 * @param {*} value The value to check.
2118 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
2119 * @example
2120 *
2121 * _.isObject({});
2122 * // => true
2123 *
2124 * _.isObject([1, 2, 3]);
2125 * // => true
2126 *
2127 * _.isObject(_.noop);
2128 * // => true
2129 *
2130 * _.isObject(null);
2131 * // => false
2132 */
2133function isObject(value) {
2134 var type = typeof value;
2135 return !!value && (type == 'object' || type == 'function');
2136}
2137
2138/**
2139 * Checks if `value` is object-like. A value is object-like if it's not `null`
2140 * and has a `typeof` result of "object".
2141 *
2142 * @static
2143 * @memberOf _
2144 * @since 4.0.0
2145 * @category Lang
2146 * @param {*} value The value to check.
2147 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
2148 * @example
2149 *
2150 * _.isObjectLike({});
2151 * // => true
2152 *
2153 * _.isObjectLike([1, 2, 3]);
2154 * // => true
2155 *
2156 * _.isObjectLike(_.noop);
2157 * // => false
2158 *
2159 * _.isObjectLike(null);
2160 * // => false
2161 */
2162function isObjectLike(value) {
2163 return !!value && typeof value == 'object';
2164}
2165
2166/**
2167 * Checks if `value` is classified as a `Symbol` primitive or object.
2168 *
2169 * @static
2170 * @memberOf _
2171 * @since 4.0.0
2172 * @category Lang
2173 * @param {*} value The value to check.
2174 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
2175 * @example
2176 *
2177 * _.isSymbol(Symbol.iterator);
2178 * // => true
2179 *
2180 * _.isSymbol('abc');
2181 * // => false
2182 */
2183function isSymbol(value) {
2184 return typeof value == 'symbol' ||
2185 (isObjectLike(value) && objectToString.call(value) == symbolTag);
2186}
2187
2188/**
2189 * Checks if `value` is classified as a typed array.
2190 *
2191 * @static
2192 * @memberOf _
2193 * @since 3.0.0
2194 * @category Lang
2195 * @param {*} value The value to check.
2196 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
2197 * @example
2198 *
2199 * _.isTypedArray(new Uint8Array);
2200 * // => true
2201 *
2202 * _.isTypedArray([]);
2203 * // => false
2204 */
2205var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
2206
2207/**
2208 * Converts `value` to a string. An empty string is returned for `null`
2209 * and `undefined` values. The sign of `-0` is preserved.
2210 *
2211 * @static
2212 * @memberOf _
2213 * @since 4.0.0
2214 * @category Lang
2215 * @param {*} value The value to process.
2216 * @returns {string} Returns the string.
2217 * @example
2218 *
2219 * _.toString(null);
2220 * // => ''
2221 *
2222 * _.toString(-0);
2223 * // => '-0'
2224 *
2225 * _.toString([1, 2, 3]);
2226 * // => '1,2,3'
2227 */
2228function toString(value) {
2229 return value == null ? '' : baseToString(value);
2230}
2231
2232/**
2233 * Gets the value at `path` of `object`. If the resolved value is
2234 * `undefined`, the `defaultValue` is returned in its place.
2235 *
2236 * @static
2237 * @memberOf _
2238 * @since 3.7.0
2239 * @category Object
2240 * @param {Object} object The object to query.
2241 * @param {Array|string} path The path of the property to get.
2242 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
2243 * @returns {*} Returns the resolved value.
2244 * @example
2245 *
2246 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
2247 *
2248 * _.get(object, 'a[0].b.c');
2249 * // => 3
2250 *
2251 * _.get(object, ['a', '0', 'b', 'c']);
2252 * // => 3
2253 *
2254 * _.get(object, 'a.b.c', 'default');
2255 * // => 'default'
2256 */
2257function get(object, path, defaultValue) {
2258 var result = object == null ? undefined : baseGet(object, path);
2259 return result === undefined ? defaultValue : result;
2260}
2261
2262/**
2263 * Checks if `path` is a direct or inherited property of `object`.
2264 *
2265 * @static
2266 * @memberOf _
2267 * @since 4.0.0
2268 * @category Object
2269 * @param {Object} object The object to query.
2270 * @param {Array|string} path The path to check.
2271 * @returns {boolean} Returns `true` if `path` exists, else `false`.
2272 * @example
2273 *
2274 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
2275 *
2276 * _.hasIn(object, 'a');
2277 * // => true
2278 *
2279 * _.hasIn(object, 'a.b');
2280 * // => true
2281 *
2282 * _.hasIn(object, ['a', 'b']);
2283 * // => true
2284 *
2285 * _.hasIn(object, 'b');
2286 * // => false
2287 */
2288function hasIn(object, path) {
2289 return object != null && hasPath(object, path, baseHasIn);
2290}
2291
2292/**
2293 * Creates an array of the own enumerable property names of `object`.
2294 *
2295 * **Note:** Non-object values are coerced to objects. See the
2296 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
2297 * for more details.
2298 *
2299 * @static
2300 * @since 0.1.0
2301 * @memberOf _
2302 * @category Object
2303 * @param {Object} object The object to query.
2304 * @returns {Array} Returns the array of property names.
2305 * @example
2306 *
2307 * function Foo() {
2308 * this.a = 1;
2309 * this.b = 2;
2310 * }
2311 *
2312 * Foo.prototype.c = 3;
2313 *
2314 * _.keys(new Foo);
2315 * // => ['a', 'b'] (iteration order is not guaranteed)
2316 *
2317 * _.keys('hi');
2318 * // => ['0', '1']
2319 */
2320function keys(object) {
2321 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
2322}
2323
2324/**
2325 * This method returns the first argument it receives.
2326 *
2327 * @static
2328 * @since 0.1.0
2329 * @memberOf _
2330 * @category Util
2331 * @param {*} value Any value.
2332 * @returns {*} Returns `value`.
2333 * @example
2334 *
2335 * var object = { 'a': 1 };
2336 *
2337 * console.log(_.identity(object) === object);
2338 * // => true
2339 */
2340function identity(value) {
2341 return value;
2342}
2343
2344/**
2345 * Creates a function that returns the value at `path` of a given object.
2346 *
2347 * @static
2348 * @memberOf _
2349 * @since 2.4.0
2350 * @category Util
2351 * @param {Array|string} path The path of the property to get.
2352 * @returns {Function} Returns the new accessor function.
2353 * @example
2354 *
2355 * var objects = [
2356 * { 'a': { 'b': 2 } },
2357 * { 'a': { 'b': 1 } }
2358 * ];
2359 *
2360 * _.map(objects, _.property('a.b'));
2361 * // => [2, 1]
2362 *
2363 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
2364 * // => [1, 2]
2365 */
2366function property(path) {
2367 return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
2368}
2369
2370module.exports = keyBy;