Add _.differenceBy, _.intersectionBy, _.isArrayLikeObject, _.pullAllBy, _.unionBy, and _.xorBy.

This commit is contained in:
John-David Dalton
2015-10-04 21:44:41 -07:00
parent 0eaa10f578
commit 69e6389369
2 changed files with 393 additions and 268 deletions

532
lodash.js
View File

@@ -2221,8 +2221,8 @@
} }
/** /**
* The base implementation of `_.difference` without support for individual * The base implementation of `_.difference` without support for excluding
* values to exclude. * multiple arrays of values.
* *
* @private * @private
* @param {Array} array The array to inspect. * @param {Array} array The array to inspect.
@@ -2230,37 +2230,53 @@
* @returns {Array} Returns the new array of filtered values. * @returns {Array} Returns the new array of filtered values.
*/ */
function baseDifference(array, values) { function baseDifference(array, values) {
var length = array.length, return baseDifferenceBy(array, values);
result = []; }
/**
* The base implementation of `_.differenceBy` without support for callback
* shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Array} values The values to exclude.
* @param {Function} [iteratee] The function invoked per element.
* @returns {Array} Returns the new array of filtered values.
*/
function baseDifferenceBy(array, values, iteratee) {
var index = -1,
indexOf = baseIndexOf,
isCommon = true,
length = array.length,
result = [],
valuesLength = values.length;
if (!length) { if (!length) {
return result; return result;
} }
var index = -1, if (iteratee) {
indexOf = getIndexOf(), values = arrayMap(values, function(value) { return iteratee(value); });
isCommon = indexOf === baseIndexOf, }
cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? new SetCache(values) : null, if (values.length >= LARGE_ARRAY_SIZE) {
valuesLength = values.length;
if (cache) {
indexOf = cacheIndexOf; indexOf = cacheIndexOf;
isCommon = false; isCommon = false;
values = cache; values = new SetCache(values);
} }
outer: outer:
while (++index < length) { while (++index < length) {
var value = array[index]; var value = array[index],
computed = iteratee ? iteratee(value) : value;
if (isCommon && value === value) { if (isCommon && computed === computed) {
var valuesIndex = valuesLength; var valuesIndex = valuesLength;
while (valuesIndex--) { while (valuesIndex--) {
if (values[valuesIndex] === value) { if (values[valuesIndex] === computed) {
continue outer; continue outer;
} }
} }
result.push(value); result.push(value);
} }
else if (indexOf(values, value, 0) < 0) { else if (indexOf(values, computed, 0) < 0) {
result.push(value); result.push(value);
} }
} }
@@ -2370,7 +2386,7 @@
while (++index < length) { while (++index < length) {
var value = array[index]; var value = array[index];
if (isObject(value) && isArrayLike(value) && if (isArrayLikeObject(value) &&
(isStrict || isArray(value) || isArguments(value))) { (isStrict || isArray(value) || isArguments(value))) {
if (isDeep) { if (isDeep) {
// Recursively flatten arrays (susceptible to call stack limits). // Recursively flatten arrays (susceptible to call stack limits).
@@ -2512,6 +2528,68 @@
return object != null && key in Object(object); return object != null && key in Object(object);
} }
/**
* The base implementation of `_.intersection` that accepts an array of arrays
* to inspect.
*
* @private
* @param {Array} arrays The arrays to inspect.
* @returns {Array} Returns the new array of shared values.
*/
function baseIntersection(arrays) {
return baseIntersectionBy(arrays);
}
/**
* The base implementation of `_.intersectionBy` without support for callback
* shorthands.
*
* @private
* @param {Array} arrays The arrays to inspect.
* @param {Function} [iteratee] The function invoked per element.
* @returns {Array} Returns the new array of shared values.
*/
function baseIntersectionBy(arrays, iteratee) {
var othLength = arrays.length,
othIndex = othLength,
caches = Array(othLength),
result = [];
while (othIndex--) {
var array = arrays[othIndex];
if (iteratee) {
array = arrayMap(array, function(value) { return iteratee(value); });
}
caches[othIndex] = (iteratee || array.length >= 120) ? new SetCache(othIndex && array) : null;
}
array = arrays[0];
var index = -1,
length = array ? array.length : 0,
seen = caches[0];
outer:
while (++index < length) {
var value = array[index],
computed = iteratee ? iteratee(value) : value;
if ((seen ? cacheIndexOf(seen, computed) : baseIndexOf(result, computed, 0)) < 0) {
var othIndex = othLength;
while (--othIndex) {
var cache = caches[othIndex];
if ((cache ? cacheIndexOf(cache, computed) : baseIndexOf(arrays[othIndex], computed, 0)) < 0) {
continue outer;
}
}
if (seen) {
seen.push(computed);
}
result.push(value);
}
}
return result;
}
/** /**
* The base implementation of `_.isEqual` which supports partial comparisons * The base implementation of `_.isEqual` which supports partial comparisons
* and tracks traversed objects. * and tracks traversed objects.
@@ -2842,7 +2920,7 @@
if (isArray(srcValue) || isTypedArray(srcValue)) { if (isArray(srcValue) || isTypedArray(srcValue)) {
newValue = isArray(oldValue) newValue = isArray(oldValue)
? oldValue ? oldValue
: ((isObject(oldValue) && isArrayLike(oldValue)) ? copyArray(oldValue) : baseClone(srcValue)); : ((isArrayLikeObject(oldValue)) ? copyArray(oldValue) : baseClone(srcValue));
} }
else if (isPlainObject(srcValue) || isArguments(srcValue)) { else if (isPlainObject(srcValue) || isArguments(srcValue)) {
newValue = isArguments(oldValue) newValue = isArguments(oldValue)
@@ -2886,7 +2964,7 @@
* *
* @private * @private
* @param {Object} object The source object. * @param {Object} object The source object.
* @param {Function} predicate The function invoked per iteration. * @param {Function} predicate The function invoked per property.
* @returns {Object} Returns the new object. * @returns {Object} Returns the new object.
*/ */
function basePickBy(object, predicate) { function basePickBy(object, predicate) {
@@ -2925,6 +3003,51 @@
}; };
} }
/**
* The base implementation of `_.pullAll`.
*
* @private
* @param {Array} array The array to modify.
* @param {Array} values The values to remove.
* @returns {Array} Returns `array`.
*/
function basePullAll(array, values) {
return basePullAllBy(array, values);
}
/**
* The base implementation of `_.pullAllBy` without support for callback
* shorthands.
*
* @private
* @param {Array} array The array to modify.
* @param {Array} values The values to remove.
* @param {Function} [iteratee] The function invoked per element.
* @returns {Array} Returns `array`.
*/
function basePullAllBy(array, values, iteratee) {
var index = -1,
length = values.length,
seen = array;
if (iteratee) {
seen = arrayMap(array, function(value) { return iteratee(value); });
}
while (++index < length) {
var fromIndex = 0,
value = values[index],
computed = iteratee ? iteratee(value) : value;
while ((fromIndex = baseIndexOf(seen, computed, fromIndex)) > -1) {
if (seen !== array) {
splice.call(seen, fromIndex, 1);
}
splice.call(array, fromIndex, 1);
}
}
return array;
}
/** /**
* The base implementation of `_.pullAt` without support for individual * The base implementation of `_.pullAt` without support for individual
* index arguments or capturing the removed elements. * index arguments or capturing the removed elements.
@@ -3118,17 +3241,15 @@
* *
* @private * @private
* @param {Array} array The array to inspect. * @param {Array} array The array to inspect.
* @param {Function} [iteratee] The function invoked per iteration. * @param {Function} [iteratee] The function invoked per element.
* @returns {Array} Returns the new duplicate free array. * @returns {Array} Returns the new duplicate free array.
*/ */
function baseSortedUniqBy(array, iteratee) { function baseSortedUniqBy(array, iteratee) {
var index = 0, var index = 0,
indexOf = getIndexOf(),
isCommon = indexOf === baseIndexOf,
length = array.length, length = array.length,
value = array[0], value = array[0],
computed = iteratee ? iteratee(value) : value, computed = iteratee ? iteratee(value) : value,
seen = isCommon ? computed : [computed], seen = computed,
resIndex = 0, resIndex = 0,
result = [value]; result = [value];
@@ -3136,15 +3257,9 @@
value = array[index], value = array[index],
computed = iteratee ? iteratee(value) : value; computed = iteratee ? iteratee(value) : value;
if (isCommon) { if ((seen === seen ? (seen !== computed) : (computed === computed))) {
if ((seen === seen ? (seen !== computed) : (computed === computed))) { seen = computed;
seen = computed; result[++resIndex] = value;
result[++resIndex] = value;
}
}
else if (indexOf(seen, computed, 0) < 0) {
seen[++resIndex] = computed;
result[resIndex] = value;
} }
} }
return result; return result;
@@ -3179,23 +3294,21 @@
* *
* @private * @private
* @param {Array} array The array to inspect. * @param {Array} array The array to inspect.
* @param {Function} [iteratee] The function invoked per iteration. * @param {Function} [iteratee] The function invoked per element.
* @returns {Array} Returns the new duplicate free array. * @returns {Array} Returns the new duplicate free array.
*/ */
function baseUniqBy(array, iteratee) { function baseUniqBy(array, iteratee) {
var index = -1, var index = -1,
indexOf = getIndexOf(), indexOf = baseIndexOf,
length = array.length, length = array.length,
isCommon = indexOf === baseIndexOf, isCommon = true,
isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = length >= LARGE_ARRAY_SIZE ? new SetCache : null,
seen = isLarge ? new SetCache : null,
result = []; result = [];
if (seen) { if (seen) {
indexOf = cacheIndexOf; indexOf = cacheIndexOf;
isCommon = false; isCommon = false;
} else { } else {
isLarge = false;
seen = iteratee ? [] : result; seen = iteratee ? [] : result;
} }
outer: outer:
@@ -3216,7 +3329,7 @@
result.push(value); result.push(value);
} }
else if (indexOf(seen, computed, 0) < 0) { else if (indexOf(seen, computed, 0) < 0) {
if (iteratee || isLarge) { if (seen !== result) {
seen.push(computed); seen.push(computed);
} }
result.push(value); result.push(value);
@@ -3283,6 +3396,39 @@
}, result); }, result);
} }
/**
* The base implementation of `_.xor` that accepts an array of arrays to inspect.
*
* @private
* @param {Array} arrays The arrays to inspect.
* @returns {Array} Returns the new array of values.
*/
function baseXor(arrays) {
return baseXorBy(arrays);
}
/**
* The base implementation of `_.xorBy` without support for callback shorthands.
*
* @private
* @param {Array} arrays The arrays to inspect.
* @param {Function} [iteratee] The function invoked per element.
* @returns {Array} Returns the new array of values.
*/
function baseXorBy(arrays, iteratee) {
var index = -1,
length = arrays.length;
while (++index < length) {
var result = result
? arrayPush(baseDifferenceBy(result, arrays[index], iteratee), baseDifferenceBy(arrays[index], result, iteratee))
: arrays[index];
}
return (result && result.length)
? baseUniqBy(result, iteratee)
: [];
}
/** /**
* Performs a binary search of `array` to determine the index at which `value` * Performs a binary search of `array` to determine the index at which `value`
* should be inserted into `array` in order to maintain its sort order. * should be inserted into `array` in order to maintain its sort order.
@@ -3322,7 +3468,7 @@
* @private * @private
* @param {Array} array The sorted array to inspect. * @param {Array} array The sorted array to inspect.
* @param {*} value The value to evaluate. * @param {*} value The value to evaluate.
* @param {Function} iteratee The function invoked per iteration. * @param {Function} iteratee The function invoked per element.
* @param {boolean} [retHighest] Specify returning the highest qualified index. * @param {boolean} [retHighest] Specify returning the highest qualified index.
* @returns {number} Returns the index at which `value` should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted into `array`.
*/ */
@@ -4218,21 +4364,6 @@
return result; return result;
} }
/**
* Gets the appropriate "indexOf" function. If the `_.indexOf` method is
* customized this function returns the custom method, otherwise it returns
* the `baseIndexOf` function. If arguments are provided the chosen function
* is invoked with them and its result is returned.
*
* @private
* @returns {Function|number} Returns the chosen function or its result.
*/
function getIndexOf(collection, target, fromIndex) {
var result = lodash.indexOf || indexOf;
result = result === indexOf ? baseIndexOf : result;
return collection ? result(collection, target, fromIndex) : result;
}
/** /**
* Gets the appropriate "iteratee" function. If the `_.iteratee` method is * Gets the appropriate "iteratee" function. If the `_.iteratee` method is
* customized this function returns the custom method, otherwise it returns * customized this function returns the custom method, otherwise it returns
@@ -4747,6 +4878,17 @@
return result; return result;
} }
/**
* Converts `value` to an array-like object if it's not one.
*
* @private
* @param {*} value The value to process.
* @returns {Array} Returns the array-like object.
*/
function toArrayLikeObject(value) {
return isArrayLikeObject(value) ? value : [];
}
/** /**
* Converts `value` to a function if it's not one. * Converts `value` to a function if it's not one.
* *
@@ -4856,15 +4998,42 @@
* @returns {Array} Returns the new array of filtered values. * @returns {Array} Returns the new array of filtered values.
* @example * @example
* *
* _.difference([1, 2, 3], [4, 2]); * _.difference([3, 2, 1], [4, 2]);
* // => [1, 3] * // => [3, 1]
*/ */
var difference = restParam(function(array, values) { var difference = restParam(function(array, values) {
return (isObject(array) && isArrayLike(array)) return isArrayLikeObject(array)
? baseDifference(array, baseFlatten(values, false, true)) ? baseDifference(array, baseFlatten(values, false, true))
: []; : [];
}); });
/**
* This method is like `_.difference` except that it accepts `iteratee` which
* is invoked for each element of `array` and `values` to generate the criterion
* by which uniqueness is computed. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @category Array
* @param {Array} array The array to inspect.
* @param {...Array} [values] The values to exclude.
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per element.
* @returns {Array} Returns the new array of filtered values.
* @example
*
* _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
* // => [3.1, 1.3]
*
* // using the `_.property` callback shorthand
* _.differenceBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
var differenceBy = restParam(function(array, values) {
return isArrayLikeObject(array)
? baseDifferenceBy(array, baseFlatten(values, false, true), getIteratee(last(values)))
: [];
});
/** /**
* Creates a slice of `array` with `n` elements dropped from the beginning. * Creates a slice of `array` with `n` elements dropped from the beginning.
* *
@@ -5252,44 +5421,41 @@
* @param {...Array} [arrays] The arrays to inspect. * @param {...Array} [arrays] The arrays to inspect.
* @returns {Array} Returns the new array of shared values. * @returns {Array} Returns the new array of shared values.
* @example * @example
* _.intersection([1, 2], [4, 2], [2, 1]); * _.intersection([2, 1], [4, 2], [1, 2]);
* // => [2] * // => [2]
*/ */
var intersection = restParam(function(arrays) { var intersection = restParam(function(arrays) {
var othLength = arrays.length, var mapped = arrayMap(arrays, toArrayLikeObject);
othIndex = othLength, return mapped[0] === arrays[0]
caches = Array(length), ? baseIntersection(mapped)
indexOf = getIndexOf(), : [];
isCommon = indexOf === baseIndexOf, });
result = [];
while (othIndex--) { /**
var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; * This method is like `_.intersection` except that it accepts `iteratee`
caches[othIndex] = (isCommon && value.length >= 120) ? new SetCache(othIndex && value) : null; * which is invoked for each element of each `arrays` to generate the criterion
} * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
var array = arrays[0], *
index = -1, * @static
length = array ? array.length : 0, * @memberOf _
seen = caches[0]; * @category Array
* @param {...Array} [arrays] The arrays to inspect.
outer: * @param {Function|Object|string} [iteratee=_.identity] The function invoked per element.
while (++index < length) { * @returns {Array} Returns the new array of shared values.
value = array[index]; * @example
if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { *
var othIndex = othLength; * _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
while (--othIndex) { * // => [2.1]
var cache = caches[othIndex]; *
if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { * // using the `_.property` callback shorthand
continue outer; * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
} * // => [{ 'x': 1 }]
} */
if (seen) { var intersectionBy = restParam(function(arrays) {
seen.push(value); var mapped = arrayMap(arrays, toArrayLikeObject);
} return mapped[0] === arrays[0]
result.push(value); ? baseIntersectionBy(mapped, getIteratee(last(arrays)))
} : [];
}
return result;
}); });
/** /**
@@ -5372,27 +5538,7 @@
* console.log(array); * console.log(array);
* // => [1, 1] * // => [1, 1]
*/ */
function pull() { var pull = restParam(pullAll);
var args = arguments,
array = args[0];
if (!(array && array.length)) {
return array;
}
var index = 0,
indexOf = getIndexOf(),
length = args.length;
while (++index < length) {
var fromIndex = 0,
value = args[index];
while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {
splice.call(array, fromIndex, 1);
}
}
return array;
}
/** /**
* This method is like `_.pull` except that it accepts an array of values to remove. * This method is like `_.pull` except that it accepts an array of values to remove.
@@ -5414,9 +5560,37 @@
* // => [1, 1] * // => [1, 1]
*/ */
function pullAll(array, values) { function pullAll(array, values) {
var args = [array]; return (array && array.length && values && values.length)
push.apply(args, values); ? basePullAll(array, values)
return pull.apply(undefined, args); : array;
}
/**
* This method is like `_.pullAll` except that it accepts `iteratee` which is
* invoked for each element of `array` and `values` to to generate the criterion
* by which uniqueness is computed. The iteratee is invoked with one argument: (value).
*
* **Note:** Unlike `_.differenceBy`, this method mutates `array`.
*
* @static
* @memberOf _
* @category Array
* @param {Array} array The array to modify.
* @param {Array} values The values to remove.
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per element.
* @returns {Array} Returns `array`.
* @example
*
* var array = [1, 2, 3, 1, 2, 3];
*
* _.pull(array, [2, 3]);
* console.log(array);
* // => [1, 1]
*/
function pullAllBy(array, values, iteratee) {
return (array && array.length && values && values.length)
? basePullAllBy(array, values, getIteratee(iteratee))
: array;
} }
/** /**
@@ -5890,13 +6064,37 @@
* @returns {Array} Returns the new array of combined values. * @returns {Array} Returns the new array of combined values.
* @example * @example
* *
* _.union([1, 2], [4, 2], [2, 1]); * _.union([2, 1], [4, 2], [1, 2]);
* // => [1, 2, 4] * // => [2, 1, 4]
*/ */
var union = restParam(function(arrays) { var union = restParam(function(arrays) {
return baseUniq(baseFlatten(arrays, false, true)); return baseUniq(baseFlatten(arrays, false, true));
}); });
/**
* This method is like `_.union` except that it accepts `iteratee` which is
* invoked for each element of each `arrays` to generate the criterion by which
* uniqueness is computed. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per element.
* @returns {Array} Returns the new array of combined values.
* @example
*
* _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
* // => [2.1, 1.2, 4.3]
*
* // using the `_.property` callback shorthand
* _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
var unionBy = restParam(function(arrays) {
return baseUniqBy(baseFlatten(arrays, false, true), getIteratee(last(arrays)));
});
/** /**
* Creates a duplicate-free version of an array, using * Creates a duplicate-free version of an array, using
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
@@ -5969,7 +6167,7 @@
} }
var length = 0; var length = 0;
array = arrayFilter(array, function(group) { array = arrayFilter(array, function(group) {
if (isObject(group) && isArrayLike(group)) { if (isArrayLikeObject(group)) {
length = nativeMax(group.length, length); length = nativeMax(group.length, length);
return true; return true;
} }
@@ -6029,7 +6227,7 @@
* // => [3] * // => [3]
*/ */
var without = restParam(function(array, values) { var without = restParam(function(array, values) {
return (isObject(array) && isArrayLike(array)) return isArrayLikeObject(array)
? baseDifference(array, values) ? baseDifference(array, values)
: []; : [];
}); });
@@ -6045,25 +6243,36 @@
* @returns {Array} Returns the new array of values. * @returns {Array} Returns the new array of values.
* @example * @example
* *
* _.xor([1, 2], [4, 2]); * _.xor([2, 1], [4, 2]);
* // => [1, 4] * // => [1, 4]
*/ */
function xor() { var xor = restParam(function(arrays) {
var index = -1, return baseXor(arrayFilter(arrays, isArrayLikeObject));
length = arguments.length; });
while (++index < length) { /**
var array = arguments[index]; * This method is like `_.xor` except that it accepts `iteratee` which is
if (isObject(array) && isArrayLike(array)) { * invoked for each element of each `arrays` to generate the criterion by which
var result = result * uniqueness is computed. The iteratee is invoked with one argument: (value).
? arrayPush(baseDifference(result, array), baseDifference(array, result)) *
: array; * @static
} * @memberOf _
} * @category Array
return (result && result.length) * @param {...Array} [arrays] The arrays to inspect.
? baseUniq(result) * @param {Function|Object|string} [iteratee=_.identity] The function invoked per element.
: []; * @returns {Array} Returns the new array of values.
} * @example
*
* _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor);
* // => [1.2, 4.3]
*
* // using the `_.property` callback shorthand
* _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 2 }]
*/
var xorBy = restParam(function(arrays) {
return baseXorBy(arrayFilter(arrays, isArrayLikeObject), getIteratee(last(arrays)));
});
/** /**
* Creates an array of grouped elements, the first of which contains the first * Creates an array of grouped elements, the first of which contains the first
@@ -6771,7 +6980,7 @@
} }
return isString(collection) return isString(collection)
? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1) ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1)
: (!!length && getIndexOf(collection, target, fromIndex) > -1); : (!!length && baseIndexOf(collection, target, fromIndex) > -1);
} }
/** /**
@@ -8615,7 +8824,7 @@
*/ */
function isArguments(value) { function isArguments(value) {
// Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode.
return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, 'callee') && return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
(!propertyIsEnumerable.call(value, 'callee') || objToString.call(value) == argsTag); (!propertyIsEnumerable.call(value, 'callee') || objToString.call(value) == argsTag);
} }
@@ -8633,7 +8842,13 @@
* _.isArray([1, 2, 3]); * _.isArray([1, 2, 3]);
* // => true * // => true
* *
* _.isArray(function() { return arguments; }()); * _.isArray(document.body.children);
* // => false
*
* _.isArray('abc');
* // => false
*
* _.isArray(_.noop);
* // => false * // => false
*/ */
var isArray = Array.isArray; var isArray = Array.isArray;
@@ -8654,7 +8869,10 @@
* _.isArrayLike([1, 2, 3]); * _.isArrayLike([1, 2, 3]);
* // => true * // => true
* *
* _.isArrayLike(function() { return arguments; }()); * _.isArrayLike(document.body.children);
* // => true
*
* _.isArrayLike('abc');
* // => true * // => true
* *
* _.isArrayLike(_.noop); * _.isArrayLike(_.noop);
@@ -8665,6 +8883,34 @@
!(typeof value == 'function' && isFunction(value)) && isLength(getLength(value)); !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value));
} }
/**
* This method is like `_.isArrayLike` except that it also checks if `value`
* is an object.
*
* @static
* @memberOf _
* @type Function
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array-like object, else `false`.
* @example
*
* _.isArrayLikeObject([1, 2, 3]);
* // => true
*
* _.isArrayLikeObject(document.body.children);
* // => true
*
* _.isArrayLikeObject('abc');
* // => false
*
* _.isArrayLikeObject(_.noop);
* // => false
*/
function isArrayLikeObject(value) {
return isObject(value) && isArrayLike(value);
}
/** /**
* Checks if `value` is classified as a boolean primitive or object. * Checks if `value` is classified as a boolean primitive or object.
* *
@@ -12393,6 +12639,7 @@
lodash.defer = defer; lodash.defer = defer;
lodash.delay = delay; lodash.delay = delay;
lodash.difference = difference; lodash.difference = difference;
lodash.differenceBy = differenceBy;
lodash.disj = disj; lodash.disj = disj;
lodash.drop = drop; lodash.drop = drop;
lodash.dropRight = dropRight; lodash.dropRight = dropRight;
@@ -12411,6 +12658,7 @@
lodash.groupBy = groupBy; lodash.groupBy = groupBy;
lodash.initial = initial; lodash.initial = initial;
lodash.intersection = intersection; lodash.intersection = intersection;
lodash.intersectionBy = intersectionBy;
lodash.invert = invert; lodash.invert = invert;
lodash.invoke = invoke; lodash.invoke = invoke;
lodash.iteratee = iteratee; lodash.iteratee = iteratee;
@@ -12445,6 +12693,7 @@
lodash.propertyOf = propertyOf; lodash.propertyOf = propertyOf;
lodash.pull = pull; lodash.pull = pull;
lodash.pullAll = pullAll; lodash.pullAll = pullAll;
lodash.pullAllBy = pullAllBy;
lodash.pullAt = pullAt; lodash.pullAt = pullAt;
lodash.range = range; lodash.range = range;
lodash.rearg = rearg; lodash.rearg = rearg;
@@ -12475,6 +12724,7 @@
lodash.toPlainObject = toPlainObject; lodash.toPlainObject = toPlainObject;
lodash.transform = transform; lodash.transform = transform;
lodash.union = union; lodash.union = union;
lodash.unionBy = unionBy;
lodash.uniq = uniq; lodash.uniq = uniq;
lodash.uniqBy = uniqBy; lodash.uniqBy = uniqBy;
lodash.unset = unset; lodash.unset = unset;
@@ -12486,6 +12736,7 @@
lodash.words = words; lodash.words = words;
lodash.wrap = wrap; lodash.wrap = wrap;
lodash.xor = xor; lodash.xor = xor;
lodash.xorBy = xorBy;
lodash.zip = zip; lodash.zip = zip;
lodash.zipObject = zipObject; lodash.zipObject = zipObject;
lodash.zipWith = zipWith; lodash.zipWith = zipWith;
@@ -12541,6 +12792,7 @@
lodash.isArguments = isArguments; lodash.isArguments = isArguments;
lodash.isArray = isArray; lodash.isArray = isArray;
lodash.isArrayLike = isArrayLike; lodash.isArrayLike = isArrayLike;
lodash.isArrayLikeObject = isArrayLikeObject;
lodash.isBoolean = isBoolean; lodash.isBoolean = isBoolean;
lodash.isDate = isDate; lodash.isDate = isDate;
lodash.isElement = isElement; lodash.isElement = isElement;

View File

@@ -6702,133 +6702,6 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('custom `_.indexOf` methods');
(function() {
function Foo() {}
function custom(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array.length;
while (++index < length) {
var other = array[index];
if (other === value || (value instanceof Foo && other instanceof Foo)) {
return index;
}
}
return -1;
}
var array = [1, new Foo, 3, new Foo],
sorted = [1, 3, new Foo, new Foo],
indexOf = _.indexOf;
var largeArray = _.times(LARGE_ARRAY_SIZE, function() {
return new Foo;
});
QUnit.test('`_.includes` should work with a custom `_.indexOf` method', function(assert) {
assert.expect(2);
if (!isModularize) {
_.indexOf = custom;
assert.ok(_.includes(array, new Foo));
assert.ok(_.includes({ 'a': 1, 'b': new Foo, 'c': 3 }, new Foo));
_.indexOf = indexOf;
}
else {
skipTest(assert, 2);
}
});
QUnit.test('`_.difference` should work with a custom `_.indexOf` method', function(assert) {
assert.expect(2);
if (!isModularize) {
_.indexOf = custom;
assert.deepEqual(_.difference(array, [new Foo]), [1, 3]);
assert.deepEqual(_.difference(array, largeArray), [1, 3]);
_.indexOf = indexOf;
}
else {
skipTest(assert, 2);
}
});
QUnit.test('`_.intersection` should work with a custom `_.indexOf` method', function(assert) {
assert.expect(2);
if (!isModularize) {
_.indexOf = custom;
assert.deepEqual(_.intersection(array, [new Foo]), [array[1]]);
assert.deepEqual(_.intersection(largeArray, [new Foo]), [array[1]]);
_.indexOf = indexOf;
}
else {
skipTest(assert, 2);
}
});
QUnit.test('`_.uniq` should work with a custom `_.indexOf` method', function(assert) {
assert.expect(2);
if (!isModularize) {
_.indexOf = custom;
assert.deepEqual(_.uniq(array), array.slice(0, 3));
assert.deepEqual(_.uniq(largeArray), [largeArray[0]]);
_.indexOf = indexOf;
}
else {
skipTest(assert, 2);
}
});
QUnit.test('`_.uniqBy` should work with a custom `_.indexOf` method', function(assert) {
assert.expect(2);
if (!isModularize) {
_.indexOf = custom;
assert.deepEqual(_.uniqBy(array, _.identity), array.slice(0, 3));
assert.deepEqual(_.uniqBy(largeArray, _.identity), [largeArray[0]]);
_.indexOf = indexOf;
}
else {
skipTest(assert, 2);
}
});
QUnit.test('`_.sortedUniq` should work with a custom `_.indexOf` method', function(assert) {
assert.expect(2);
if (!isModularize) {
_.indexOf = custom;
assert.deepEqual(_.sortedUniq(sorted), sorted.slice(0, 3));
assert.deepEqual(_.sortedUniq(largeArray), [largeArray[0]]);
_.indexOf = indexOf;
}
else {
skipTest(assert, 2);
}
});
QUnit.test('`_.sortedUniqBy` should work with a custom `_.indexOf` method', function(assert) {
assert.expect(2);
if (!isModularize) {
_.indexOf = custom;
assert.deepEqual(_.sortedUniqBy(sorted, _.identity), sorted.slice(0, 3));
assert.deepEqual(_.sortedUniqBy(largeArray, _.identity), [largeArray[0]]);
_.indexOf = indexOf;
}
else {
skipTest(assert, 2);
}
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.initial'); QUnit.module('lodash.initial');
(function() { (function() {
@@ -21232,7 +21105,7 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey); var acceptFalsey = _.difference(allMethods, rejectFalsey);
QUnit.test('should accept falsey arguments', function(assert) { QUnit.test('should accept falsey arguments', function(assert) {
assert.expect(245); assert.expect(251);
var emptyArrays = _.map(falsey, _.constant([])); var emptyArrays = _.map(falsey, _.constant([]));