UNPKG

17.5 kBJavaScriptView Raw
1/**
2 * lodash 4.0.2 (Custom Build) <https://lodash.com/>
3 * Build: `lodash modularize exports="npm" -o ./`
4 * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
5 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
6 * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
7 * Available under MIT license <https://lodash.com/license>
8 */
9var SetCache = require('lodash._setcache'),
10 arrayIncludes = require('lodash._arrayincludes'),
11 arrayIncludesWith = require('lodash._arrayincludeswith'),
12 arrayMap = require('lodash._arraymap'),
13 baseFlatten = require('lodash._baseflatten'),
14 baseIsEqual = require('lodash._baseisequal'),
15 baseIsMatch = require('lodash._baseismatch'),
16 cacheHas = require('lodash._cachehas'),
17 get = require('lodash.get'),
18 hasIn = require('lodash.hasin'),
19 rest = require('lodash.rest'),
20 toPairs = require('lodash.topairs');
21
22/** Used to compose bitmasks for comparison styles. */
23var UNORDERED_COMPARE_FLAG = 1,
24 PARTIAL_COMPARE_FLAG = 2;
25
26/** Used as the size to enable large array optimizations. */
27var LARGE_ARRAY_SIZE = 200;
28
29/** Used as references for various `Number` constants. */
30var INFINITY = 1 / 0,
31 MAX_SAFE_INTEGER = 9007199254740991;
32
33/** `Object#toString` result references. */
34var funcTag = '[object Function]',
35 genTag = '[object GeneratorFunction]',
36 symbolTag = '[object Symbol]';
37
38/** Used to match property names within property paths. */
39var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
40 reIsPlainProp = /^\w*$/,
41 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g;
42
43/** Used to match backslashes in property paths. */
44var reEscapeChar = /\\(\\)?/g;
45
46/**
47 * The base implementation of `_.unary` without support for storing wrapper metadata.
48 *
49 * @private
50 * @param {Function} func The function to cap arguments for.
51 * @returns {Function} Returns the new function.
52 */
53function baseUnary(func) {
54 return function(value) {
55 return func(value);
56 };
57}
58
59/** Used for built-in method references. */
60var objectProto = global.Object.prototype;
61
62/**
63 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
64 * of values.
65 */
66var objectToString = objectProto.toString;
67
68/** Built-in value references. */
69var Symbol = global.Symbol;
70
71/** Used to convert symbols to primitives and strings. */
72var symbolProto = Symbol ? Symbol.prototype : undefined,
73 symbolToString = Symbol ? symbolProto.toString : undefined;
74
75/**
76 * The base implementation of methods like `_.difference` without support for
77 * excluding multiple arrays or iteratee shorthands.
78 *
79 * @private
80 * @param {Array} array The array to inspect.
81 * @param {Array} values The values to exclude.
82 * @param {Function} [iteratee] The iteratee invoked per element.
83 * @param {Function} [comparator] The comparator invoked per element.
84 * @returns {Array} Returns the new array of filtered values.
85 */
86function baseDifference(array, values, iteratee, comparator) {
87 var index = -1,
88 includes = arrayIncludes,
89 isCommon = true,
90 length = array.length,
91 result = [],
92 valuesLength = values.length;
93
94 if (!length) {
95 return result;
96 }
97 if (iteratee) {
98 values = arrayMap(values, baseUnary(iteratee));
99 }
100 if (comparator) {
101 includes = arrayIncludesWith;
102 isCommon = false;
103 }
104 else if (values.length >= LARGE_ARRAY_SIZE) {
105 includes = cacheHas;
106 isCommon = false;
107 values = new SetCache(values);
108 }
109 outer:
110 while (++index < length) {
111 var value = array[index],
112 computed = iteratee ? iteratee(value) : value;
113
114 if (isCommon && computed === computed) {
115 var valuesIndex = valuesLength;
116 while (valuesIndex--) {
117 if (values[valuesIndex] === computed) {
118 continue outer;
119 }
120 }
121 result.push(value);
122 }
123 else if (!includes(values, computed, comparator)) {
124 result.push(value);
125 }
126 }
127 return result;
128}
129
130/**
131 * The base implementation of `_.get` without support for default values.
132 *
133 * @private
134 * @param {Object} object The object to query.
135 * @param {Array|string} path The path of the property to get.
136 * @returns {*} Returns the resolved value.
137 */
138function baseGet(object, path) {
139 path = isKey(path, object) ? [path + ''] : baseToPath(path);
140
141 var index = 0,
142 length = path.length;
143
144 while (object != null && index < length) {
145 object = object[path[index++]];
146 }
147 return (index && index == length) ? object : undefined;
148}
149
150/**
151 * The base implementation of `_.iteratee`.
152 *
153 * @private
154 * @param {*} [value=_.identity] The value to convert to an iteratee.
155 * @returns {Function} Returns the iteratee.
156 */
157function baseIteratee(value) {
158 var type = typeof value;
159 if (type == 'function') {
160 return value;
161 }
162 if (value == null) {
163 return identity;
164 }
165 if (type == 'object') {
166 return isArray(value)
167 ? baseMatchesProperty(value[0], value[1])
168 : baseMatches(value);
169 }
170 return property(value);
171}
172
173/**
174 * The base implementation of `_.matches` which doesn't clone `source`.
175 *
176 * @private
177 * @param {Object} source The object of property values to match.
178 * @returns {Function} Returns the new function.
179 */
180function baseMatches(source) {
181 var matchData = getMatchData(source);
182 if (matchData.length == 1 && matchData[0][2]) {
183 var key = matchData[0][0],
184 value = matchData[0][1];
185
186 return function(object) {
187 if (object == null) {
188 return false;
189 }
190 return object[key] === value &&
191 (value !== undefined || (key in Object(object)));
192 };
193 }
194 return function(object) {
195 return object === source || baseIsMatch(object, source, matchData);
196 };
197}
198
199/**
200 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
201 *
202 * @private
203 * @param {string} path The path of the property to get.
204 * @param {*} srcValue The value to match.
205 * @returns {Function} Returns the new function.
206 */
207function baseMatchesProperty(path, srcValue) {
208 return function(object) {
209 var objValue = get(object, path);
210 return (objValue === undefined && objValue === srcValue)
211 ? hasIn(object, path)
212 : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
213 };
214}
215
216/**
217 * The base implementation of `_.property` without support for deep paths.
218 *
219 * @private
220 * @param {string} key The key of the property to get.
221 * @returns {Function} Returns the new function.
222 */
223function baseProperty(key) {
224 return function(object) {
225 return object == null ? undefined : object[key];
226 };
227}
228
229/**
230 * A specialized version of `baseProperty` which supports deep paths.
231 *
232 * @private
233 * @param {Array|string} path The path of the property to get.
234 * @returns {Function} Returns the new function.
235 */
236function basePropertyDeep(path) {
237 return function(object) {
238 return baseGet(object, path);
239 };
240}
241
242/**
243 * The base implementation of `_.toPath` which only converts `value` to a
244 * path if it's not one.
245 *
246 * @private
247 * @param {*} value The value to process.
248 * @returns {Array} Returns the property path array.
249 */
250function baseToPath(value) {
251 return isArray(value) ? value : stringToPath(value);
252}
253
254/**
255 * Gets the "length" property value of `object`.
256 *
257 * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
258 * that affects Safari on at least iOS 8.1-8.3 ARM64.
259 *
260 * @private
261 * @param {Object} object The object to query.
262 * @returns {*} Returns the "length" value.
263 */
264var getLength = baseProperty('length');
265
266/**
267 * Gets the property names, values, and compare flags of `object`.
268 *
269 * @private
270 * @param {Object} object The object to query.
271 * @returns {Array} Returns the match data of `object`.
272 */
273function getMatchData(object) {
274 var result = toPairs(object),
275 length = result.length;
276
277 while (length--) {
278 result[length][2] = isStrictComparable(result[length][1]);
279 }
280 return result;
281}
282
283/**
284 * Checks if `value` is a property name and not a property path.
285 *
286 * @private
287 * @param {*} value The value to check.
288 * @param {Object} [object] The object to query keys on.
289 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
290 */
291function isKey(value, object) {
292 if (typeof value == 'number') {
293 return true;
294 }
295 return !isArray(value) &&
296 (reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
297 (object != null && value in Object(object)));
298}
299
300/**
301 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
302 *
303 * @private
304 * @param {*} value The value to check.
305 * @returns {boolean} Returns `true` if `value` if suitable for strict
306 * equality comparisons, else `false`.
307 */
308function isStrictComparable(value) {
309 return value === value && !isObject(value);
310}
311
312/**
313 * Converts `string` to a property path array.
314 *
315 * @private
316 * @param {string} string The string to convert.
317 * @returns {Array} Returns the property path array.
318 */
319function stringToPath(string) {
320 var result = [];
321 toString(string).replace(rePropName, function(match, number, quote, string) {
322 result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
323 });
324 return result;
325}
326
327/**
328 * This method is like `_.difference` except that it accepts `iteratee` which
329 * is invoked for each element of `array` and `values` to generate the criterion
330 * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
331 *
332 * @static
333 * @memberOf _
334 * @category Array
335 * @param {Array} array The array to inspect.
336 * @param {...Array} [values] The values to exclude.
337 * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
338 * @returns {Array} Returns the new array of filtered values.
339 * @example
340 *
341 * _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
342 * // => [3.1, 1.3]
343 *
344 * // using the `_.property` iteratee shorthand
345 * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
346 * // => [{ 'x': 2 }]
347 */
348var differenceBy = rest(function(array, values) {
349 var iteratee = last(values);
350 if (isArrayLikeObject(iteratee)) {
351 iteratee = undefined;
352 }
353 return isArrayLikeObject(array)
354 ? baseDifference(array, baseFlatten(values, false, true), baseIteratee(iteratee))
355 : [];
356});
357
358/**
359 * Gets the last element of `array`.
360 *
361 * @static
362 * @memberOf _
363 * @category Array
364 * @param {Array} array The array to query.
365 * @returns {*} Returns the last element of `array`.
366 * @example
367 *
368 * _.last([1, 2, 3]);
369 * // => 3
370 */
371function last(array) {
372 var length = array ? array.length : 0;
373 return length ? array[length - 1] : undefined;
374}
375
376/**
377 * Checks if `value` is classified as an `Array` object.
378 *
379 * @static
380 * @memberOf _
381 * @type Function
382 * @category Lang
383 * @param {*} value The value to check.
384 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
385 * @example
386 *
387 * _.isArray([1, 2, 3]);
388 * // => true
389 *
390 * _.isArray(document.body.children);
391 * // => false
392 *
393 * _.isArray('abc');
394 * // => false
395 *
396 * _.isArray(_.noop);
397 * // => false
398 */
399var isArray = Array.isArray;
400
401/**
402 * Checks if `value` is array-like. A value is considered array-like if it's
403 * not a function and has a `value.length` that's an integer greater than or
404 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
405 *
406 * @static
407 * @memberOf _
408 * @type Function
409 * @category Lang
410 * @param {*} value The value to check.
411 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
412 * @example
413 *
414 * _.isArrayLike([1, 2, 3]);
415 * // => true
416 *
417 * _.isArrayLike(document.body.children);
418 * // => true
419 *
420 * _.isArrayLike('abc');
421 * // => true
422 *
423 * _.isArrayLike(_.noop);
424 * // => false
425 */
426function isArrayLike(value) {
427 return value != null &&
428 !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value));
429}
430
431/**
432 * This method is like `_.isArrayLike` except that it also checks if `value`
433 * is an object.
434 *
435 * @static
436 * @memberOf _
437 * @type Function
438 * @category Lang
439 * @param {*} value The value to check.
440 * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`.
441 * @example
442 *
443 * _.isArrayLikeObject([1, 2, 3]);
444 * // => true
445 *
446 * _.isArrayLikeObject(document.body.children);
447 * // => true
448 *
449 * _.isArrayLikeObject('abc');
450 * // => false
451 *
452 * _.isArrayLikeObject(_.noop);
453 * // => false
454 */
455function isArrayLikeObject(value) {
456 return isObjectLike(value) && isArrayLike(value);
457}
458
459/**
460 * Checks if `value` is classified as a `Function` object.
461 *
462 * @static
463 * @memberOf _
464 * @category Lang
465 * @param {*} value The value to check.
466 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
467 * @example
468 *
469 * _.isFunction(_);
470 * // => true
471 *
472 * _.isFunction(/abc/);
473 * // => false
474 */
475function isFunction(value) {
476 // The use of `Object#toString` avoids issues with the `typeof` operator
477 // in Safari 8 which returns 'object' for typed array constructors, and
478 // PhantomJS 1.9 which returns 'function' for `NodeList` instances.
479 var tag = isObject(value) ? objectToString.call(value) : '';
480 return tag == funcTag || tag == genTag;
481}
482
483/**
484 * Checks if `value` is a valid array-like length.
485 *
486 * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
487 *
488 * @static
489 * @memberOf _
490 * @category Lang
491 * @param {*} value The value to check.
492 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
493 * @example
494 *
495 * _.isLength(3);
496 * // => true
497 *
498 * _.isLength(Number.MIN_VALUE);
499 * // => false
500 *
501 * _.isLength(Infinity);
502 * // => false
503 *
504 * _.isLength('3');
505 * // => false
506 */
507function isLength(value) {
508 return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
509}
510
511/**
512 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
513 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
514 *
515 * @static
516 * @memberOf _
517 * @category Lang
518 * @param {*} value The value to check.
519 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
520 * @example
521 *
522 * _.isObject({});
523 * // => true
524 *
525 * _.isObject([1, 2, 3]);
526 * // => true
527 *
528 * _.isObject(_.noop);
529 * // => true
530 *
531 * _.isObject(null);
532 * // => false
533 */
534function isObject(value) {
535 // Avoid a V8 JIT bug in Chrome 19-20.
536 // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
537 var type = typeof value;
538 return !!value && (type == 'object' || type == 'function');
539}
540
541/**
542 * Checks if `value` is object-like. A value is object-like if it's not `null`
543 * and has a `typeof` result of "object".
544 *
545 * @static
546 * @memberOf _
547 * @category Lang
548 * @param {*} value The value to check.
549 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
550 * @example
551 *
552 * _.isObjectLike({});
553 * // => true
554 *
555 * _.isObjectLike([1, 2, 3]);
556 * // => true
557 *
558 * _.isObjectLike(_.noop);
559 * // => false
560 *
561 * _.isObjectLike(null);
562 * // => false
563 */
564function isObjectLike(value) {
565 return !!value && typeof value == 'object';
566}
567
568/**
569 * Checks if `value` is classified as a `Symbol` primitive or object.
570 *
571 * @static
572 * @memberOf _
573 * @category Lang
574 * @param {*} value The value to check.
575 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
576 * @example
577 *
578 * _.isSymbol(Symbol.iterator);
579 * // => true
580 *
581 * _.isSymbol('abc');
582 * // => false
583 */
584function isSymbol(value) {
585 return typeof value == 'symbol' ||
586 (isObjectLike(value) && objectToString.call(value) == symbolTag);
587}
588
589/**
590 * Converts `value` to a string if it's not one. An empty string is returned
591 * for `null` and `undefined` values. The sign of `-0` is preserved.
592 *
593 * @static
594 * @memberOf _
595 * @category Lang
596 * @param {*} value The value to process.
597 * @returns {string} Returns the string.
598 * @example
599 *
600 * _.toString(null);
601 * // => ''
602 *
603 * _.toString(-0);
604 * // => '-0'
605 *
606 * _.toString([1, 2, 3]);
607 * // => '1,2,3'
608 */
609function toString(value) {
610 // Exit early for strings to avoid a performance hit in some environments.
611 if (typeof value == 'string') {
612 return value;
613 }
614 if (value == null) {
615 return '';
616 }
617 if (isSymbol(value)) {
618 return Symbol ? symbolToString.call(value) : '';
619 }
620 var result = (value + '');
621 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
622}
623
624/**
625 * This method returns the first argument provided to it.
626 *
627 * @static
628 * @memberOf _
629 * @category Util
630 * @param {*} value Any value.
631 * @returns {*} Returns `value`.
632 * @example
633 *
634 * var object = { 'user': 'fred' };
635 *
636 * _.identity(object) === object;
637 * // => true
638 */
639function identity(value) {
640 return value;
641}
642
643/**
644 * Creates a function that returns the value at `path` of a given object.
645 *
646 * @static
647 * @memberOf _
648 * @category Util
649 * @param {Array|string} path The path of the property to get.
650 * @returns {Function} Returns the new function.
651 * @example
652 *
653 * var objects = [
654 * { 'a': { 'b': { 'c': 2 } } },
655 * { 'a': { 'b': { 'c': 1 } } }
656 * ];
657 *
658 * _.map(objects, _.property('a.b.c'));
659 * // => [2, 1]
660 *
661 * _.map(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
662 * // => [1, 2]
663 */
664function property(path) {
665 return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
666}
667
668module.exports = differenceBy;