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