|
|
|
/**
|
|
|
|
* lodash 4.5.0 (Custom Build) <https://lodash.com/>
|
|
|
|
* Build: `lodash modularize exports="npm" -o ./`
|
|
|
|
* Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
|
|
|
|
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
|
|
|
* Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|
|
|
* Available under MIT license <https://lodash.com/license>
|
|
|
|
*/
|
|
|
|
var SetCache = require('lodash._setcache'),
|
|
|
|
createSet = require('lodash._createset');
|
|
|
|
|
|
|
|
/** Used as the size to enable large array optimizations. */
|
|
|
|
var LARGE_ARRAY_SIZE = 200;
|
|
|
|
|
|
|
|
/** Used to stand-in for `undefined` hash values. */
|
|
|
|
var HASH_UNDEFINED = '__lodash_hash_undefined__';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A specialized version of `_.includes` for arrays without support for
|
|
|
|
* specifying an index to search from.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Array} array The array to search.
|
|
|
|
* @param {*} target The value to search for.
|
|
|
|
* @returns {boolean} Returns `true` if `target` is found, else `false`.
|
|
|
|
*/
|
|
|
|
function arrayIncludes(array, value) {
|
|
|
|
return !!array.length && baseIndexOf(array, value, 0) > -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A specialized version of `_.includesWith` for arrays without support for
|
|
|
|
* specifying an index to search from.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Array} array The array to search.
|
|
|
|
* @param {*} target The value to search for.
|
|
|
|
* @param {Function} comparator The comparator invoked per element.
|
|
|
|
* @returns {boolean} Returns `true` if `target` is found, else `false`.
|
|
|
|
*/
|
|
|
|
function arrayIncludesWith(array, value, comparator) {
|
|
|
|
var index = -1,
|
|
|
|
length = array.length;
|
|
|
|
|
|
|
|
while (++index < length) {
|
|
|
|
if (comparator(value, array[index])) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The base implementation of `_.indexOf` without `fromIndex` bounds checks.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Array} array The array to search.
|
|
|
|
* @param {*} value The value to search for.
|
|
|
|
* @param {number} fromIndex The index to search from.
|
|
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
|
|
*/
|
|
|
|
function baseIndexOf(array, value, fromIndex) {
|
|
|
|
if (value !== value) {
|
|
|
|
return indexOfNaN(array, fromIndex);
|
|
|
|
}
|
|
|
|
var index = fromIndex - 1,
|
|
|
|
length = array.length;
|
|
|
|
|
|
|
|
while (++index < length) {
|
|
|
|
if (array[index] === value) {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the index at which the first occurrence of `NaN` is found in `array`.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Array} array The array to search.
|
|
|
|
* @param {number} fromIndex The index to search from.
|
|
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
|
|
* @returns {number} Returns the index of the matched `NaN`, else `-1`.
|
|
|
|
*/
|
|
|
|
function indexOfNaN(array, fromIndex, fromRight) {
|
|
|
|
var length = array.length,
|
|
|
|
index = fromIndex + (fromRight ? 0 : -1);
|
|
|
|
|
|
|
|
while ((fromRight ? index-- : ++index < length)) {
|
|
|
|
var other = array[index];
|
|
|
|
if (other !== other) {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts `set` to an array.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Object} set The set to convert.
|
|
|
|
* @returns {Array} Returns the converted array.
|
|
|
|
*/
|
|
|
|
function setToArray(set) {
|
|
|
|
var index = -1,
|
|
|
|
result = Array(set.size);
|
|
|
|
|
|
|
|
set.forEach(function(value) {
|
|
|
|
result[++index] = value;
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if `value` is in `cache`.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Object} cache The set cache to search.
|
|
|
|
* @param {*} value The value to search for.
|
|
|
|
* @returns {number} Returns `true` if `value` is found, else `false`.
|
|
|
|
*/
|
|
|
|
function cacheHas(cache, value) {
|
|
|
|
var map = cache.__data__;
|
|
|
|
if (isKeyable(value)) {
|
|
|
|
var data = map.__data__,
|
|
|
|
hash = typeof value == 'string' ? data.string : data.hash;
|
|
|
|
|
|
|
|
return hash[value] === HASH_UNDEFINED;
|
|
|
|
}
|
|
|
|
return map.has(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The base implementation of `_.uniqBy` without support for iteratee shorthands.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Array} array The array to inspect.
|
|
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
|
|
*/
|
|
|
|
function baseUniq(array, iteratee, comparator) {
|
|
|
|
var index = -1,
|
|
|
|
includes = arrayIncludes,
|
|
|
|
length = array.length,
|
|
|
|
isCommon = true,
|
|
|
|
result = [],
|
|
|
|
seen = result;
|
|
|
|
|
|
|
|
if (comparator) {
|
|
|
|
isCommon = false;
|
|
|
|
includes = arrayIncludesWith;
|
|
|
|
}
|
|
|
|
else if (length >= LARGE_ARRAY_SIZE) {
|
|
|
|
var set = iteratee ? null : createSet(array);
|
|
|
|
if (set) {
|
|
|
|
return setToArray(set);
|
|
|
|
}
|
|
|
|
isCommon = false;
|
|
|
|
includes = cacheHas;
|
|
|
|
seen = new SetCache;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
seen = iteratee ? [] : result;
|
|
|
|
}
|
|
|
|
outer:
|
|
|
|
while (++index < length) {
|
|
|
|
var value = array[index],
|
|
|
|
computed = iteratee ? iteratee(value) : value;
|
|
|
|
|
|
|
|
if (isCommon && computed === computed) {
|
|
|
|
var seenIndex = seen.length;
|
|
|
|
while (seenIndex--) {
|
|
|
|
if (seen[seenIndex] === computed) {
|
|
|
|
continue outer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (iteratee) {
|
|
|
|
seen.push(computed);
|
|
|
|
}
|
|
|
|
result.push(value);
|
|
|
|
}
|
|
|
|
else if (!includes(seen, computed, comparator)) {
|
|
|
|
if (seen !== result) {
|
|
|
|
seen.push(computed);
|
|
|
|
}
|
|
|
|
result.push(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if `value` is suitable for use as unique object key.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {*} value The value to check.
|
|
|
|
* @returns {boolean} Returns `true` if `value` is suitable, else `false`.
|
|
|
|
*/
|
|
|
|
function isKeyable(value) {
|
|
|
|
var type = typeof value;
|
|
|
|
return type == 'number' || type == 'boolean' ||
|
|
|
|
(type == 'string' && value != '__proto__') || value == null;
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = baseUniq;
|