mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-09 18:37:50 +00:00
Loosen restrictions of _.intersection and others to accept array-like objects and add isArrayLike helper. [closes #1163]
This commit is contained in:
@@ -1829,8 +1829,8 @@
|
|||||||
*/
|
*/
|
||||||
function baseAt(collection, props) {
|
function baseAt(collection, props) {
|
||||||
var index = -1,
|
var index = -1,
|
||||||
|
isArr = isArrayLike(collection),
|
||||||
length = collection.length,
|
length = collection.length,
|
||||||
isArr = isLength(length),
|
|
||||||
propsLength = props.length,
|
propsLength = props.length,
|
||||||
result = Array(propsLength);
|
result = Array(propsLength);
|
||||||
|
|
||||||
@@ -2169,8 +2169,8 @@
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Array} array The array to flatten.
|
* @param {Array} array The array to flatten.
|
||||||
* @param {boolean} isDeep Specify a deep flatten.
|
* @param {boolean} [isDeep] Specify a deep flatten.
|
||||||
* @param {boolean} isStrict Restrict flattening to arrays and `arguments` objects.
|
* @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
|
||||||
* @returns {Array} Returns the new flattened array.
|
* @returns {Array} Returns the new flattened array.
|
||||||
*/
|
*/
|
||||||
function baseFlatten(array, isDeep, isStrict) {
|
function baseFlatten(array, isDeep, isStrict) {
|
||||||
@@ -2181,8 +2181,8 @@
|
|||||||
|
|
||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
var value = array[index];
|
var value = array[index];
|
||||||
|
if (isObjectLike(value) && isArrayLike(value) &&
|
||||||
if (isObjectLike(value) && isLength(value.length) && (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).
|
||||||
value = baseFlatten(value, isDeep, isStrict);
|
value = baseFlatten(value, isDeep, isStrict);
|
||||||
@@ -2483,8 +2483,7 @@
|
|||||||
*/
|
*/
|
||||||
function baseMap(collection, iteratee) {
|
function baseMap(collection, iteratee) {
|
||||||
var index = -1,
|
var index = -1,
|
||||||
length = getLength(collection),
|
result = isArrayLike(collection) ? Array(collection.length) : [];
|
||||||
result = isLength(length) ? Array(length) : [];
|
|
||||||
|
|
||||||
baseEach(collection, function(value, key, collection) {
|
baseEach(collection, function(value, key, collection) {
|
||||||
result[++index] = iteratee(value, key, collection);
|
result[++index] = iteratee(value, key, collection);
|
||||||
@@ -2584,7 +2583,7 @@
|
|||||||
if (!isObject(object)) {
|
if (!isObject(object)) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source));
|
var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source));
|
||||||
if (!isSrcArr) {
|
if (!isSrcArr) {
|
||||||
var props = keys(source);
|
var props = keys(source);
|
||||||
push.apply(props, getSymbols(source));
|
push.apply(props, getSymbols(source));
|
||||||
@@ -2647,10 +2646,10 @@
|
|||||||
|
|
||||||
if (isCommon) {
|
if (isCommon) {
|
||||||
result = srcValue;
|
result = srcValue;
|
||||||
if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) {
|
if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
|
||||||
result = isArray(value)
|
result = isArray(value)
|
||||||
? value
|
? value
|
||||||
: (getLength(value) ? arrayCopy(value) : []);
|
: (isArrayLike(value) ? arrayCopy(value) : []);
|
||||||
}
|
}
|
||||||
else if (isPlainObject(srcValue) || isArguments(srcValue)) {
|
else if (isPlainObject(srcValue) || isArguments(srcValue)) {
|
||||||
result = isArguments(value)
|
result = isArguments(value)
|
||||||
@@ -3292,11 +3291,11 @@
|
|||||||
*/
|
*/
|
||||||
function createBaseEach(eachFunc, fromRight) {
|
function createBaseEach(eachFunc, fromRight) {
|
||||||
return function(collection, iteratee) {
|
return function(collection, iteratee) {
|
||||||
var length = collection ? getLength(collection) : 0;
|
if (!isArrayLike(collection)) {
|
||||||
if (!isLength(length)) {
|
|
||||||
return eachFunc(collection, iteratee);
|
return eachFunc(collection, iteratee);
|
||||||
}
|
}
|
||||||
var index = fromRight ? length : -1,
|
var length = collection.length,
|
||||||
|
index = fromRight ? length : -1,
|
||||||
iterable = toObject(collection);
|
iterable = toObject(collection);
|
||||||
|
|
||||||
while ((fromRight ? index-- : ++index < length)) {
|
while ((fromRight ? index-- : ++index < length)) {
|
||||||
@@ -4309,6 +4308,17 @@
|
|||||||
return func == null ? undefined : func.apply(object, args);
|
return func == null ? undefined : func.apply(object, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if `value` is array-like.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {*} value The value to check.
|
||||||
|
* @returns {boolean} Returns `true` if `value` is array-like, else `false`.
|
||||||
|
*/
|
||||||
|
function isArrayLike(value) {
|
||||||
|
return value != null && isLength(getLength(value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if `value` is a valid array-like index.
|
* Checks if `value` is a valid array-like index.
|
||||||
*
|
*
|
||||||
@@ -4337,13 +4347,9 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var type = typeof index;
|
var type = typeof index;
|
||||||
if (type == 'number') {
|
if (type == 'number'
|
||||||
var length = getLength(object),
|
? (isArrayLike(object) && isIndex(index, object.length))
|
||||||
prereq = isLength(length) && isIndex(index, length);
|
: (type == 'string' && index in object)) {
|
||||||
} else {
|
|
||||||
prereq = type == 'string' && index in object;
|
|
||||||
}
|
|
||||||
if (prereq) {
|
|
||||||
var other = object[index];
|
var other = object[index];
|
||||||
return value === value ? (value === other) : (other !== other);
|
return value === value ? (value === other) : (other !== other);
|
||||||
}
|
}
|
||||||
@@ -4657,7 +4663,7 @@
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
if (!isLength(getLength(value))) {
|
if (!isArrayLike(value)) {
|
||||||
return values(value);
|
return values(value);
|
||||||
}
|
}
|
||||||
if (lodash.support.unindexedChars && isString(value)) {
|
if (lodash.support.unindexedChars && isString(value)) {
|
||||||
@@ -4806,7 +4812,7 @@
|
|||||||
* // => [1, 3]
|
* // => [1, 3]
|
||||||
*/
|
*/
|
||||||
var difference = restParam(function(array, values) {
|
var difference = restParam(function(array, values) {
|
||||||
return (isArray(array) || isArguments(array))
|
return isArrayLike(array)
|
||||||
? baseDifference(array, baseFlatten(values, false, true))
|
? baseDifference(array, baseFlatten(values, false, true))
|
||||||
: [];
|
: [];
|
||||||
});
|
});
|
||||||
@@ -5294,7 +5300,7 @@
|
|||||||
|
|
||||||
while (++argsIndex < argsLength) {
|
while (++argsIndex < argsLength) {
|
||||||
var value = arguments[argsIndex];
|
var value = arguments[argsIndex];
|
||||||
if (isArray(value) || isArguments(value)) {
|
if (isArrayLike(value)) {
|
||||||
args.push(value);
|
args.push(value);
|
||||||
caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null);
|
caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null);
|
||||||
}
|
}
|
||||||
@@ -5954,7 +5960,7 @@
|
|||||||
length = 0;
|
length = 0;
|
||||||
|
|
||||||
array = arrayFilter(array, function(group) {
|
array = arrayFilter(array, function(group) {
|
||||||
if (isArray(group) || isArguments(group)) {
|
if (isArrayLike(group)) {
|
||||||
length = nativeMax(group.length, length);
|
length = nativeMax(group.length, length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -6021,7 +6027,7 @@
|
|||||||
* // => [3]
|
* // => [3]
|
||||||
*/
|
*/
|
||||||
var without = restParam(function(array, values) {
|
var without = restParam(function(array, values) {
|
||||||
return (isArray(array) || isArguments(array))
|
return isArrayLike(array)
|
||||||
? baseDifference(array, values)
|
? baseDifference(array, values)
|
||||||
: [];
|
: [];
|
||||||
});
|
});
|
||||||
@@ -6046,7 +6052,7 @@
|
|||||||
|
|
||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
var array = arguments[index];
|
var array = arguments[index];
|
||||||
if (isArray(array) || isArguments(array)) {
|
if (isArrayLike(array)) {
|
||||||
var result = result
|
var result = result
|
||||||
? baseDifference(result, array).concat(baseDifference(array, result))
|
? baseDifference(result, array).concat(baseDifference(array, result))
|
||||||
: array;
|
: array;
|
||||||
@@ -6419,8 +6425,7 @@
|
|||||||
* // => ['barney', 'pebbles']
|
* // => ['barney', 'pebbles']
|
||||||
*/
|
*/
|
||||||
var at = restParam(function(collection, props) {
|
var at = restParam(function(collection, props) {
|
||||||
var length = collection ? getLength(collection) : 0;
|
if (isArrayLike(collection)) {
|
||||||
if (isLength(length)) {
|
|
||||||
collection = toIterable(collection);
|
collection = toIterable(collection);
|
||||||
}
|
}
|
||||||
return baseAt(collection, baseFlatten(props));
|
return baseAt(collection, baseFlatten(props));
|
||||||
@@ -6921,8 +6926,7 @@
|
|||||||
var index = -1,
|
var index = -1,
|
||||||
isFunc = typeof path == 'function',
|
isFunc = typeof path == 'function',
|
||||||
isProp = isKey(path),
|
isProp = isKey(path),
|
||||||
length = getLength(collection),
|
result = isArrayLike(collection) ? Array(collection.length) : [];
|
||||||
result = isLength(length) ? Array(length) : [];
|
|
||||||
|
|
||||||
baseEach(collection, function(value) {
|
baseEach(collection, function(value) {
|
||||||
var func = isFunc ? path : (isProp && value != null && value[path]);
|
var func = isFunc ? path : (isProp && value != null && value[path]);
|
||||||
@@ -8661,15 +8665,13 @@
|
|||||||
* // => false
|
* // => false
|
||||||
*/
|
*/
|
||||||
function isArguments(value) {
|
function isArguments(value) {
|
||||||
var length = isObjectLike(value) ? value.length : undefined;
|
return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag;
|
||||||
return isLength(length) && objToString.call(value) == argsTag;
|
|
||||||
}
|
}
|
||||||
// Fallback for environments without a `toStringTag` for `arguments` objects.
|
// Fallback for environments without a `toStringTag` for `arguments` objects.
|
||||||
if (!support.argsTag) {
|
if (!support.argsTag) {
|
||||||
isArguments = function(value) {
|
isArguments = function(value) {
|
||||||
var length = isObjectLike(value) ? value.length : undefined;
|
return isObjectLike(value) && isArrayLike(value) &&
|
||||||
return isLength(length) && hasOwnProperty.call(value, 'callee') &&
|
hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
|
||||||
!propertyIsEnumerable.call(value, 'callee');
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8791,10 +8793,9 @@
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var length = getLength(value);
|
if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||
|
||||||
if (isLength(length) && (isArray(value) || isString(value) || isArguments(value) ||
|
|
||||||
(isObjectLike(value) && isFunction(value.splice)))) {
|
(isObjectLike(value) && isFunction(value.splice)))) {
|
||||||
return !length;
|
return !value.length;
|
||||||
}
|
}
|
||||||
return !keys(value).length;
|
return !keys(value).length;
|
||||||
}
|
}
|
||||||
@@ -9785,12 +9786,9 @@
|
|||||||
* // => ['0', '1']
|
* // => ['0', '1']
|
||||||
*/
|
*/
|
||||||
var keys = !nativeKeys ? shimKeys : function(object) {
|
var keys = !nativeKeys ? shimKeys : function(object) {
|
||||||
if (object) {
|
var Ctor = object != null && object.constructor;
|
||||||
var Ctor = object.constructor,
|
|
||||||
length = object.length;
|
|
||||||
}
|
|
||||||
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
|
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
|
||||||
(typeof object == 'function' ? lodash.support.enumPrototypes : isLength(length))) {
|
(typeof object == 'function' ? lodash.support.enumPrototypes : isArrayLike(object))) {
|
||||||
return shimKeys(object);
|
return shimKeys(object);
|
||||||
}
|
}
|
||||||
return isObject(object) ? nativeKeys(object) : [];
|
return isObject(object) ? nativeKeys(object) : [];
|
||||||
|
|||||||
@@ -3855,12 +3855,11 @@
|
|||||||
deepEqual(_.difference([1, NaN, 3], largeArray), [1, 3]);
|
deepEqual(_.difference([1, NaN, 3], largeArray), [1, 3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should ignore values that are not arrays or `arguments` objects', 4, function() {
|
test('should ignore values that are not array-like', 3, function() {
|
||||||
var array = [1, null, 3];
|
var array = [1, null, 3];
|
||||||
deepEqual(_.difference(args, 3, { '0': 1 }), [1, 2, 3]);
|
deepEqual(_.difference(args, 3, { '0': 1 }), [1, 2, 3]);
|
||||||
deepEqual(_.difference(null, array, 1), []);
|
deepEqual(_.difference(null, array, 1), []);
|
||||||
deepEqual(_.difference(array, args, null), [null]);
|
deepEqual(_.difference(array, args, null), [null]);
|
||||||
deepEqual(_.difference('abc', array, 'b'), []);
|
|
||||||
});
|
});
|
||||||
}(1, 2, 3));
|
}(1, 2, 3));
|
||||||
|
|
||||||
@@ -16532,10 +16531,6 @@
|
|||||||
var array = [1, 2, 3, 1, 2, 3];
|
var array = [1, 2, 3, 1, 2, 3];
|
||||||
deepEqual(_.without(array, 1, 2), [3, 3]);
|
deepEqual(_.without(array, 1, 2), [3, 3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should treat string values for `array` as empty', 1, function() {
|
|
||||||
deepEqual(_.without('abc', 'b'), []);
|
|
||||||
});
|
|
||||||
}(1, 2, 3));
|
}(1, 2, 3));
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|||||||
Reference in New Issue
Block a user