Split out _.sortedIndexOf, _.sortedLastIndexOf, _.sortedUniq, and _.sortedUniqBy.

This commit is contained in:
John-David Dalton
2015-08-26 08:27:16 -07:00
parent 790d6331f8
commit e30a20120c
2 changed files with 278 additions and 173 deletions

238
lodash.js
View File

@@ -587,34 +587,6 @@
return result; return result;
} }
/**
* An implementation of `_.uniq` optimized for sorted arrays without support
* for callback shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The function invoked per iteration.
* @returns {Array} Returns the new duplicate free array.
*/
function sortedUniq(array, iteratee) {
var seen,
index = -1,
length = array.length,
resIndex = -1,
result = [];
while (++index < length) {
var value = array[index],
computed = iteratee ? iteratee(value, index, array) : value;
if (!index || seen !== computed) {
seen = computed;
result[++resIndex] = value;
}
}
return result;
}
/** /**
* Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
* character of `string`. * character of `string`.
@@ -2648,6 +2620,43 @@
}); });
} }
/**
* The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
* support for callback shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The function invoked per iteration.
* @returns {Array} Returns the new duplicate free array.
*/
function baseSortedUniq(array, iteratee) {
var index = -1,
indexOf = getIndexOf(),
isCommon = indexOf === baseIndexOf,
length = array.length,
seen = isCommon ? undefined : [],
resIndex = -1,
result = [];
while (++index < length) {
var value = array[index],
computed = iteratee ? iteratee(value, index, array) : value;
if (isCommon && value === value) {
if (seen !== computed || !index) {
seen = computed
result[++resIndex] = value;
}
} else {
if (!index || indexOf(seen, computed, 0) < 0) {
seen.push(computed);
result[++resIndex] = value;
}
}
}
return result;
}
/** /**
* The base implementation of `_.uniq` and `_.uniqBy` without support for * The base implementation of `_.uniq` and `_.uniqBy` without support for
* callback shorthands. * callback shorthands.
@@ -4662,8 +4671,7 @@
* @category Array * @category Array
* @param {Array} array The array to search. * @param {Array} array The array to search.
* @param {*} value The value to search for. * @param {*} value The value to search for.
* @param {boolean|number} [fromIndex=0] The index to search from or `true` * @param {number} [fromIndex=0] The index to search from.
* to perform a binary search on a sorted array.
* @returns {number} Returns the index of the matched value, else `-1`. * @returns {number} Returns the index of the matched value, else `-1`.
* @example * @example
* *
@@ -4673,26 +4681,15 @@
* // using `fromIndex` * // using `fromIndex`
* _.indexOf([1, 2, 1, 2], 2, 2); * _.indexOf([1, 2, 1, 2], 2, 2);
* // => 3 * // => 3
*
* // performing a binary search
* _.indexOf([1, 1, 2, 2], 2, true);
* // => 2
*/ */
function indexOf(array, value, fromIndex) { function indexOf(array, value, fromIndex) {
var length = array ? array.length : 0; var length = array ? array.length : 0;
if (!length) { if (!length) {
return -1; return -1;
} }
if (typeof fromIndex == 'number') { if (fromIndex) {
fromIndex = toInteger(fromIndex); fromIndex = toInteger(fromIndex);
fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
} else if (fromIndex) {
var index = binaryIndex(array, value);
if (index < length &&
(value === value ? (value === array[index]) : (array[index] !== array[index]))) {
return index;
}
return -1;
} }
return baseIndexOf(array, value, fromIndex || 0); return baseIndexOf(array, value, fromIndex || 0);
} }
@@ -4792,8 +4789,7 @@
* @category Array * @category Array
* @param {Array} array The array to search. * @param {Array} array The array to search.
* @param {*} value The value to search for. * @param {*} value The value to search for.
* @param {boolean|number} [fromIndex=array.length-1] The index to search from * @param {number} [fromIndex=array.length-1] The index to search from.
* or `true` to perform a binary search on a sorted array.
* @returns {number} Returns the index of the matched value, else `-1`. * @returns {number} Returns the index of the matched value, else `-1`.
* @example * @example
* *
@@ -4803,10 +4799,6 @@
* // using `fromIndex` * // using `fromIndex`
* _.lastIndexOf([1, 2, 1, 2], 2, 2); * _.lastIndexOf([1, 2, 1, 2], 2, 2);
* // => 1 * // => 1
*
* // performing a binary search
* _.lastIndexOf([1, 1, 2, 2], 2, true);
* // => 3
*/ */
function lastIndexOf(array, value, fromIndex) { function lastIndexOf(array, value, fromIndex) {
var length = array ? array.length : 0; var length = array ? array.length : 0;
@@ -4814,16 +4806,9 @@
return -1; return -1;
} }
var index = length; var index = length;
if (typeof fromIndex == 'number') { if (fromIndex !== undefined) {
index = toInteger(fromIndex); index = toInteger(fromIndex);
index = (index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1)) + 1; index = (index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1)) + 1;
} else if (fromIndex) {
index = binaryIndex(array, value, true) - 1;
var other = array[index];
if (value === value ? (value === other) : (other !== other)) {
return index;
}
return -1;
} }
if (value !== value) { if (value !== value) {
return indexOfNaN(array, index, true); return indexOfNaN(array, index, true);
@@ -5050,6 +5035,33 @@
return binaryIndexBy(array, value, getIteratee(iteratee)); return binaryIndexBy(array, value, getIteratee(iteratee));
} }
/**
* This method is like `_.indexOf` except that it performs a binary
* search on a sorted `array`.
*
* @static
* @memberOf _
* @category Array
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @returns {number} Returns the index of the matched value, else `-1`.
* @example
*
* _.sortedIndexOf([1, 1, 2, 2], 2);
* // => 2
*/
function sortedIndexOf(array, value) {
var length = array ? array.length : 0;
if (length) {
var index = binaryIndex(array, value);
if (index < length &&
(value === value ? (value === array[index]) : (array[index] !== array[index]))) {
return index;
}
}
return -1;
}
/** /**
* This method is like `_.sortedIndex` except that it returns the highest * This method is like `_.sortedIndex` except that it returns the highest
* index at which `value` should be inserted into `array` in order to * index at which `value` should be inserted into `array` in order to
@@ -5092,6 +5104,77 @@
return binaryIndexBy(array, value, getIteratee(iteratee), true); return binaryIndexBy(array, value, getIteratee(iteratee), true);
} }
/**
* This method is like `_.lastIndexOf` except that it performs a binary
* search on a sorted `array`.
*
* @static
* @memberOf _
* @category Array
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @returns {number} Returns the index of the matched value, else `-1`.
* @example
*
* _.sortedLastIndexOf([1, 1, 2, 2], 2);
* // => 3
*/
function sortedLastIndexOf(array, value) {
var length = array ? array.length : 0;
if (length) {
var index = binaryIndex(array, value, true) - 1,
other = array[index];
if (value === value ? (value === other) : (other !== other)) {
return index;
}
}
return -1
}
/**
* This method is like `_.uniq` except that it's designed and optimized
* for sorted arrays.
*
* @static
* @memberOf _
* @category Array
* @param {Array} array The array to inspect.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* _.sortedUniq([1, 1, 2]);
* // => [1, 2]
*/
function sortedUniq(array) {
return (array && array.length)
? baseSortedUniq(array)
: [];
}
/**
* This method is like `_.uniqBy` except that it's designed and optimized
* for sorted arrays.
*
* @static
* @memberOf _
* @category Array
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The function invoked per iteration.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* _.sortedUniqBy([1, 1.5, 2, 2.5], function(n) {
* return Math.floor(n);
* });
* // => [1, 2]
*/
function sortedUniqBy(array, iteratee) {
return (array && array.length)
? baseSortedUniq(array, getIteratee(iteratee))
: [];
}
/** /**
* Creates a slice of `array` with `n` elements taken from the beginning. * Creates a slice of `array` with `n` elements taken from the beginning.
* *
@@ -5265,31 +5348,22 @@
* 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)
* for equality comparisons, in which only the first occurence of each element * for equality comparisons, in which only the first occurence of each element
* is kept. Providing `true` for `isSorted` performs a faster search algorithm * is kept.
* for sorted arrays.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Array * @category Array
* @param {Array} array The array to inspect. * @param {Array} array The array to inspect.
* @param {boolean} [isSorted] Specify the array is sorted.
* @returns {Array} Returns the new duplicate free array. * @returns {Array} Returns the new duplicate free array.
* @example * @example
* *
* _.uniq([2, 1, 2]); * _.uniq([2, 1, 2]);
* // => [2, 1] * // => [2, 1]
*
* // using `isSorted`
* _.uniq([1, 1, 2], true);
* // => [1, 2]
*/ */
function uniq(array, isSorted) { function uniq(array) {
if (!(array && array.length)) { return (array && array.length)
return []; ? baseUniq(array)
} : [];
return (isSorted && typeof isSorted == 'boolean' && getIndexOf() === baseIndexOf)
? sortedUniq(array)
: baseUniq(array);
} }
/** /**
@@ -5301,7 +5375,6 @@
* @memberOf _ * @memberOf _
* @category Array * @category Array
* @param {Array} array The array to inspect. * @param {Array} array The array to inspect.
* @param {boolean} [isSorted] Specify the array is sorted.
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
* @returns {Array} Returns the new duplicate free array. * @returns {Array} Returns the new duplicate free array.
* @example * @example
@@ -5315,21 +5388,10 @@
* _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }] * // => [{ 'x': 1 }, { 'x': 2 }]
*/ */
function uniqBy(array, isSorted, iteratee) { function uniqBy(array, iteratee) {
if (!(array && array.length)) { return (array && array.length)
return []; ? baseUniq(array, getIteratee(iteratee))
} : [];
if (isSorted != null && typeof isSorted != 'boolean') {
iteratee = isSorted;
isSorted = false;
}
var toIteratee = getIteratee();
if (!(iteratee == null && toIteratee === baseIteratee)) {
iteratee = toIteratee(iteratee);
}
return (isSorted && getIndexOf() === baseIndexOf)
? sortedUniq(array, iteratee)
: baseUniq(array, iteratee);
} }
/** /**
@@ -11457,6 +11519,8 @@
lodash.slice = slice; lodash.slice = slice;
lodash.sortBy = sortBy; lodash.sortBy = sortBy;
lodash.sortByOrder = sortByOrder; lodash.sortByOrder = sortByOrder;
lodash.sortedUniq = sortedUniq;
lodash.sortedUniqBy = sortedUniqBy;
lodash.spread = spread; lodash.spread = spread;
lodash.take = take; lodash.take = take;
lodash.takeRight = takeRight; lodash.takeRight = takeRight;
@@ -11583,8 +11647,10 @@
lodash.some = some; lodash.some = some;
lodash.sortedIndex = sortedIndex; lodash.sortedIndex = sortedIndex;
lodash.sortedIndexBy = sortedIndexBy; lodash.sortedIndexBy = sortedIndexBy;
lodash.sortedIndexOf = sortedIndexOf;
lodash.sortedLastIndex = sortedLastIndex; lodash.sortedLastIndex = sortedLastIndex;
lodash.sortedLastIndexBy = sortedLastIndexBy; lodash.sortedLastIndexBy = sortedLastIndexBy;
lodash.sortedLastIndexOf = sortedLastIndexOf;
lodash.startCase = startCase; lodash.startCase = startCase;
lodash.startsWith = startsWith; lodash.startsWith = startsWith;
lodash.sum = sum; lodash.sum = sum;

View File

@@ -5778,18 +5778,6 @@
test('should coerce `fromIndex` to an integer', 1, function() { test('should coerce `fromIndex` to an integer', 1, function() {
strictEqual(_.indexOf(array, 2, 1.2), 1); strictEqual(_.indexOf(array, 2, 1.2), 1);
}); });
test('should perform a binary search when `fromIndex` is a non-number truthy value', 1, function() {
var sorted = [4, 4, 5, 5, 6, 6],
values = [true, '1', {}],
expected = _.map(values, _.constant(2));
var actual = _.map(values, function(value) {
return _.indexOf(sorted, 5, value);
});
deepEqual(actual, expected);
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -5813,6 +5801,7 @@
} }
var array = [1, new Foo, 3, new Foo], var array = [1, new Foo, 3, new Foo],
sorted = [1, 3, new Foo, new Foo],
indexOf = _.indexOf; indexOf = _.indexOf;
var largeArray = _.times(LARGE_ARRAY_SIZE, function() { var largeArray = _.times(LARGE_ARRAY_SIZE, function() {
@@ -5855,32 +5844,52 @@
} }
}); });
test('`_.uniq` should work with a custom `_.indexOf` method', 4, function() { test('`_.uniq` should work with a custom `_.indexOf` method', 2, function() {
_.each([false, true], function(param) { if (!isModularize) {
if (!isModularize) { _.indexOf = custom;
_.indexOf = custom; deepEqual(_.uniq(array), array.slice(0, 3));
deepEqual(_.uniq(array, param), array.slice(0, 3)); deepEqual(_.uniq(largeArray), [largeArray[0]]);
deepEqual(_.uniq(largeArray, param), [largeArray[0]]); _.indexOf = indexOf;
_.indexOf = indexOf; }
} else {
else { skipTest(2);
skipTest(2); }
}
});
}); });
test('`_.uniqBy` should work with a custom `_.indexOf` method', 6, function() { test('`_.uniqBy` should work with a custom `_.indexOf` method', 2, function() {
_.each([[false, _.identity], [true, _.identity], [_.identity]], function(params) { if (!isModularize) {
if (!isModularize) { _.indexOf = custom;
_.indexOf = custom; deepEqual(_.uniqBy(array, _.identity), array.slice(0, 3));
deepEqual(_.uniqBy.apply(_, [array].concat(params)), array.slice(0, 3)); deepEqual(_.uniqBy(largeArray, _.identity), [largeArray[0]]);
deepEqual(_.uniqBy.apply(_, [largeArray].concat(params)), [largeArray[0]]); _.indexOf = indexOf;
_.indexOf = indexOf; }
} else {
else { skipTest(2);
skipTest(2); }
} });
});
test('`_.sortedUniq` should work with a custom `_.indexOf` method', 2, function() {
if (!isModularize) {
_.indexOf = custom;
deepEqual(_.sortedUniq(sorted), sorted.slice(0, 3));
deepEqual(_.sortedUniq(largeArray), [largeArray[0]]);
_.indexOf = indexOf;
}
else {
skipTest(2);
}
});
test('`_.sortedUniqBy` should work with a custom `_.indexOf` method', 2, function() {
if (!isModularize) {
_.indexOf = custom;
deepEqual(_.sortedUniqBy(sorted, _.identity), sorted.slice(0, 3));
deepEqual(_.sortedUniqBy(largeArray, _.identity), [largeArray[0]]);
_.indexOf = indexOf;
}
else {
skipTest(2);
}
}); });
}()); }());
@@ -9024,9 +9033,9 @@
deepEqual(actual, expected); deepEqual(actual, expected);
}); });
test('should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`', 1, function() { test('should treat falsey `fromIndex` values correctly', 1, function() {
var expected = _.map(falsey, function(value) { var expected = _.map(falsey, function(value) {
return typeof value == 'number' ? -1 : 5; return value === undefined ? 5 : -1;
}); });
var actual = _.map(falsey, function(fromIndex) { var actual = _.map(falsey, function(fromIndex) {
@@ -9039,27 +9048,16 @@
test('should coerce `fromIndex` to an integer', 1, function() { test('should coerce `fromIndex` to an integer', 1, function() {
strictEqual(_.lastIndexOf(array, 2, 4.2), 4); strictEqual(_.lastIndexOf(array, 2, 4.2), 4);
}); });
test('should perform a binary search when `fromIndex` is a non-number truthy value', 1, function() {
var sorted = [4, 4, 5, 5, 6, 6],
values = [true, '1', {}],
expected = _.map(values, _.constant(3));
var actual = _.map(values, function(value) {
return _.lastIndexOf(sorted, 5, value);
});
deepEqual(actual, expected);
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('indexOf methods'); QUnit.module('indexOf methods');
_.each(['indexOf', 'lastIndexOf'], function(methodName) { _.each(['indexOf', 'lastIndexOf', 'sortedIndexOf', 'sortedLastIndexOf'], function(methodName) {
var func = _[methodName], var func = _[methodName],
isIndexOf = methodName == 'indexOf'; isIndexOf = !/last/i.test(methodName),
isSorted = /^sorted/.test(methodName);
test('`_.' + methodName + '` should accept a falsey `array` argument', 1, function() { test('`_.' + methodName + '` should accept a falsey `array` argument', 1, function() {
var expected = _.map(falsey, _.constant(-1)); var expected = _.map(falsey, _.constant(-1));
@@ -9094,11 +9092,20 @@
}); });
test('`_.' + methodName + '` should match `NaN`', 4, function() { test('`_.' + methodName + '` should match `NaN`', 4, function() {
var array = [1, NaN, 3, NaN, 5, NaN]; var array = isSorted
strictEqual(func(array, NaN), isIndexOf ? 1 : 5); ? [1, 2, NaN, NaN]
strictEqual(func(array, NaN, 2), isIndexOf ? 3 : 1); : [1, NaN, 3, NaN, 5, NaN];
strictEqual(func(array, NaN, -2), isIndexOf ? 5 : 3);
strictEqual(func([1, 2, NaN, NaN], NaN, true), isIndexOf ? 2 : 3); if (isSorted) {
strictEqual(func(array, NaN, true), isIndexOf ? 2 : 3);
skipTest(3);
}
else {
strictEqual(func(array, NaN), isIndexOf ? 1 : 5);
strictEqual(func(array, NaN, 2), isIndexOf ? 3 : 1);
strictEqual(func(array, NaN, -2), isIndexOf ? 5 : 3);
skipTest();
}
}); });
test('`_.' + methodName + '` should match `-0` as `0`', 2, function() { test('`_.' + methodName + '` should match `-0` as `0`', 2, function() {
@@ -14271,6 +14278,53 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('sortedIndexOf methods');
_.each(['sortedIndexOf', 'sortedLastIndexOf'], function(methodName) {
var func = _[methodName],
isSortedIndexOf = methodName == 'sortedIndexOf';
test('should perform a binary search', 1, function() {
var sorted = [4, 4, 5, 5, 6, 6];
deepEqual(func(sorted, 5), isSortedIndexOf ? 2 : 3);
});
});
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.sortedUniq');
(function() {
test('should return unique values of a sorted array', 3, function() {
var expected = [1, 2, 3];
_.each([[1, 2, 3], [1, 1, 2, 2, 3], [1, 2, 3, 3, 3, 3, 3]], function(array) {
deepEqual(_.sortedUniq(array), expected);
});
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.sortedUniqBy');
(function() {
var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
test('should work with an `iteratee` argument', 1, function() {
var array = _.sortBy(objects, 'a'),
expected = [objects[2], objects[0], objects[1]];
var actual = _.sortedUniqBy(array, function(object) {
return object.a;
});
deepEqual(actual, expected);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.spread'); QUnit.module('lodash.spread');
(function() { (function() {
@@ -15902,17 +15956,14 @@
(function() { (function() {
var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }]; var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
test('should work with an `iteratee` argument', 2, function() { test('should work with an `iteratee` argument', 1, function() {
_.each([objects, _.sortBy(objects, 'a')], function(array, index) { var expected = objects.slice(0, 3);
var isSorted = !!index,
expected = isSorted ? [objects[2], objects[0], objects[1]] : objects.slice(0, 3);
var actual = _.uniqBy(array, isSorted, function(object) { var actual = _.uniqBy(objects, function(object) {
return object.a; return object.a;
});
deepEqual(actual, expected);
}); });
deepEqual(actual, expected);
}); });
test('should provide the correct `iteratee` arguments', 1, function() { test('should provide the correct `iteratee` arguments', 1, function() {
@@ -15925,14 +15976,6 @@
deepEqual(args, [objects[0]]); deepEqual(args, [objects[0]]);
}); });
test('should work with `iteratee` without specifying `isSorted`', 1, function() {
var actual = _.uniqBy(objects, function(object) {
return object.a;
});
deepEqual(actual, objects.slice(0, 3));
});
test('should work with a "_.property" style `iteratee`', 2, function() { test('should work with a "_.property" style `iteratee`', 2, function() {
var actual = _.uniqBy(objects, 'a'); var actual = _.uniqBy(objects, 'a');
@@ -15984,13 +16027,6 @@
deepEqual(func([1, NaN, 3, NaN]), [1, NaN, 3]); deepEqual(func([1, NaN, 3, NaN]), [1, NaN, 3]);
}); });
test('`_.' + methodName + '` should work with `isSorted`', 3, function() {
var expected = [1, 2, 3];
deepEqual(func([1, 2, 3], true), expected);
deepEqual(func([1, 1, 2, 2, 3], true), expected);
deepEqual(func([1, 2, 3, 3, 3, 3, 3], true), expected);
});
test('`_.' + methodName + '` should work with large arrays', 1, function() { test('`_.' + methodName + '` should work with large arrays', 1, function() {
var largeArray = [], var largeArray = [],
expected = [0, 'a', {}], expected = [0, 'a', {}],
@@ -17148,10 +17184,11 @@
QUnit.module('"Arrays" category methods'); QUnit.module('"Arrays" category methods');
(function() { (function() {
var args = arguments, var args = (function() { return arguments; }(1, null, [3], null, 5)),
sortedArgs = (function() { return arguments; }(1, [3], 5, null, null)),
array = [1, 2, 3, 4, 5, 6]; array = [1, 2, 3, 4, 5, 6];
test('should work with `arguments` objects', 28, function() { test('should work with `arguments` objects', 30, function() {
function message(methodName) { function message(methodName) {
return '`_.' + methodName + '` should work with `arguments` objects'; return '`_.' + methodName + '` should work with `arguments` objects';
} }
@@ -17177,8 +17214,10 @@
deepEqual(_.last(args), 5, message('last')); deepEqual(_.last(args), 5, message('last'));
deepEqual(_.lastIndexOf(args, 1), 0, message('lastIndexOf')); deepEqual(_.lastIndexOf(args, 1), 0, message('lastIndexOf'));
deepEqual(_.rest(args, 4), [null, [3], null, 5], message('rest')); deepEqual(_.rest(args, 4), [null, [3], null, 5], message('rest'));
deepEqual(_.sortedIndex(args, 6), 5, message('sortedIndex')); deepEqual(_.sortedIndex(sortedArgs, 6), 3, message('sortedIndex'));
deepEqual(_.sortedLastIndex(args, 6), 5, message('sortedLastIndex')); deepEqual(_.sortedIndexOf(sortedArgs, 5), 2, message('sortedIndexOf'));
deepEqual(_.sortedLastIndex(sortedArgs, 5), 3, message('sortedLastIndex'))
deepEqual(_.sortedLastIndexOf(sortedArgs, 1), 0, message('sortedLastIndexOf'));
deepEqual(_.take(args, 2), [1, null], message('take')); deepEqual(_.take(args, 2), [1, null], message('take'));
deepEqual(_.takeRight(args, 1), [5], message('takeRight')); deepEqual(_.takeRight(args, 1), [5], message('takeRight'));
deepEqual(_.takeRightWhile(args, _.identity), [5], message('takeRightWhile')); deepEqual(_.takeRightWhile(args, _.identity), [5], message('takeRightWhile'));
@@ -17208,7 +17247,7 @@
deepEqual(_.intersection(array, null), [], message('intersection')); deepEqual(_.intersection(array, null), [], message('intersection'));
deepEqual(_.union(array, null), array, message('union')); deepEqual(_.union(array, null), array, message('union'));
}); });
}(1, null, [3], null, 5)); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -17319,7 +17358,7 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey); var acceptFalsey = _.difference(allMethods, rejectFalsey);
test('should accept falsey arguments', 224, function() { test('should accept falsey arguments', 228, function() {
var emptyArrays = _.map(falsey, _.constant([])); var emptyArrays = _.map(falsey, _.constant([]));
_.each(acceptFalsey, function(methodName) { _.each(acceptFalsey, function(methodName) {