Add fromIndex param to _.findIndex and _.findLastIndex.

This commit is contained in:
John-David Dalton
2016-05-10 20:11:52 -07:00
parent 9fa86ec712
commit 04d6e351a6
2 changed files with 80 additions and 58 deletions

View File

@@ -717,12 +717,13 @@
* @private * @private
* @param {Array} array The array to search. * @param {Array} array The array to search.
* @param {Function} predicate The function invoked per iteration. * @param {Function} predicate The function invoked per iteration.
* @param {number} fromIndex The index to search from.
* @param {boolean} [fromRight] Specify iterating from right to left. * @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {number} Returns the index of the matched value, else `-1`. * @returns {number} Returns the index of the matched value, else `-1`.
*/ */
function baseFindIndex(array, predicate, fromRight) { function baseFindIndex(array, predicate, fromIndex, fromRight) {
var length = array.length, var length = array.length,
index = fromRight ? length : -1; index = fromIndex + (fromRight ? 1 : -1);
while ((fromRight ? index-- : ++index < length)) { while ((fromRight ? index-- : ++index < length)) {
if (predicate(array[index], index, array)) { if (predicate(array[index], index, array)) {
@@ -1040,7 +1041,7 @@
*/ */
function indexOfNaN(array, fromIndex, fromRight) { function indexOfNaN(array, fromIndex, fromRight) {
var length = array.length, var length = array.length,
index = fromIndex + (fromRight ? 0 : -1); index = fromIndex + (fromRight ? 1 : -1);
while ((fromRight ? index-- : ++index < length)) { while ((fromRight ? index-- : ++index < length)) {
var other = array[index]; var other = array[index];
@@ -6428,6 +6429,7 @@
* @param {Array} array The array to search. * @param {Array} array The array to search.
* @param {Array|Function|Object|string} [predicate=_.identity] * @param {Array|Function|Object|string} [predicate=_.identity]
* The function invoked per iteration. * The function invoked per iteration.
* @param {number} [fromIndex=0] The index to search from.
* @returns {number} Returns the index of the found element, else `-1`. * @returns {number} Returns the index of the found element, else `-1`.
* @example * @example
* *
@@ -6452,10 +6454,16 @@
* _.findIndex(users, 'active'); * _.findIndex(users, 'active');
* // => 2 * // => 2
*/ */
function findIndex(array, predicate) { function findIndex(array, predicate, fromIndex) {
return (array && array.length) var length = array ? array.length : 0;
? baseFindIndex(array, getIteratee(predicate, 3)) if (!length) {
: -1; return -1;
}
var index = fromIndex == null ? 0 : toInteger(fromIndex);
if (index < 0) {
index = nativeMax(length + index, 0);
}
return baseFindIndex(array, getIteratee(predicate, 3), index);
} }
/** /**
@@ -6469,6 +6477,7 @@
* @param {Array} array The array to search. * @param {Array} array The array to search.
* @param {Array|Function|Object|string} [predicate=_.identity] * @param {Array|Function|Object|string} [predicate=_.identity]
* The function invoked per iteration. * The function invoked per iteration.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @returns {number} Returns the index of the found element, else `-1`. * @returns {number} Returns the index of the found element, else `-1`.
* @example * @example
* *
@@ -6493,10 +6502,19 @@
* _.findLastIndex(users, 'active'); * _.findLastIndex(users, 'active');
* // => 0 * // => 0
*/ */
function findLastIndex(array, predicate) { function findLastIndex(array, predicate, fromIndex) {
return (array && array.length) var length = array ? array.length : 0;
? baseFindIndex(array, getIteratee(predicate, 3), true) if (!length) {
: -1; return -1;
}
var index = length - 1;
if (fromIndex !== undefined) {
index = toInteger(fromIndex);
index = fromIndex < 0
? nativeMax(length + index, 0)
: nativeMin(index, length - 1);
}
return baseFindIndex(array, getIteratee(predicate, 3), index, true);
} }
/** /**
@@ -6643,11 +6661,11 @@
if (!length) { if (!length) {
return -1; return -1;
} }
fromIndex = toInteger(fromIndex); var index = fromIndex == null ? 0 : toInteger(fromIndex);
if (fromIndex < 0) { if (index < 0) {
fromIndex = nativeMax(length + fromIndex, 0); index = nativeMax(length + index, 0);
} }
return baseIndexOf(array, value, fromIndex); return baseIndexOf(array, value, index);
} }
/** /**
@@ -6838,7 +6856,7 @@
) + 1; ) + 1;
} }
if (value !== value) { if (value !== value) {
return indexOfNaN(array, index, true); return indexOfNaN(array, index - 1, true);
} }
while (index--) { while (index--) {
if (array[index] === value) { if (array[index] === value) {
@@ -8414,7 +8432,7 @@
function find(collection, predicate) { function find(collection, predicate) {
predicate = getIteratee(predicate, 3); predicate = getIteratee(predicate, 3);
if (isArray(collection)) { if (isArray(collection)) {
var index = baseFindIndex(collection, predicate); var index = baseFindIndex(collection, predicate, 0);
return index > -1 ? collection[index] : undefined; return index > -1 ? collection[index] : undefined;
} }
return baseFind(collection, predicate, baseEach); return baseFind(collection, predicate, baseEach);
@@ -8442,7 +8460,7 @@
function findLast(collection, predicate) { function findLast(collection, predicate) {
predicate = getIteratee(predicate, 3); predicate = getIteratee(predicate, 3);
if (isArray(collection)) { if (isArray(collection)) {
var index = baseFindIndex(collection, predicate, true); var index = baseFindIndex(collection, predicate, collection.length - 1, true);
return index > -1 ? collection[index] : undefined; return index > -1 ? collection[index] : undefined;
} }
return baseFind(collection, predicate, baseEachRight); return baseFind(collection, predicate, baseEachRight);

View File

@@ -7768,24 +7768,26 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.indexOf'); QUnit.module('lodash.findIndex and lodash.indexOf');
(function() { lodashStable.each(['findIndex', 'indexOf'], function(methodName) {
var array = [1, 2, 3, 1, 2, 3]; var array = [1, 2, 3, 1, 2, 3],
func = _[methodName],
resolve = methodName == 'findIndex' ? lodashStable.curry(lodashStable.eq) : identity;
QUnit.test('should return the index of the first matched value', function(assert) { QUnit.test('`_.' + methodName + '` should return the index of the first matched value', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.indexOf(array, 3), 2); assert.strictEqual(func(array, resolve(3)), 2);
}); });
QUnit.test('should work with a positive `fromIndex`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a positive `fromIndex`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.indexOf(array, 1, 2), 3); assert.strictEqual(func(array, resolve(1), 2), 3);
}); });
QUnit.test('should work with `fromIndex` >= `array.length`', function(assert) { QUnit.test('`_.' + methodName + '` should work with `fromIndex` >= `array.length`', function(assert) {
assert.expect(1); assert.expect(1);
var values = [6, 8, Math.pow(2, 32), Infinity], var values = [6, 8, Math.pow(2, 32), Infinity],
@@ -7793,52 +7795,52 @@
var actual = lodashStable.map(values, function(fromIndex) { var actual = lodashStable.map(values, function(fromIndex) {
return [ return [
_.indexOf(array, undefined, fromIndex), func(array, resolve(undefined), fromIndex),
_.indexOf(array, 1, fromIndex), func(array, resolve(1), fromIndex),
_.indexOf(array, '', fromIndex) func(array, resolve(''), fromIndex)
]; ];
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work with a negative `fromIndex`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a negative `fromIndex`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.indexOf(array, 2, -3), 4); assert.strictEqual(func(array, resolve(2), -3), 4);
}); });
QUnit.test('should work with a negative `fromIndex` <= `-array.length`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a negative `fromIndex` <= `-array.length`', function(assert) {
assert.expect(1); assert.expect(1);
var values = [-6, -8, -Infinity], var values = [-6, -8, -Infinity],
expected = lodashStable.map(values, alwaysZero); expected = lodashStable.map(values, alwaysZero);
var actual = lodashStable.map(values, function(fromIndex) { var actual = lodashStable.map(values, function(fromIndex) {
return _.indexOf(array, 1, fromIndex); return func(array, resolve(1), fromIndex);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should treat falsey `fromIndex` values as `0`', function(assert) { QUnit.test('`_.' + methodName + '` should treat falsey `fromIndex` values as `0`', function(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, alwaysZero); var expected = lodashStable.map(falsey, alwaysZero);
var actual = lodashStable.map(falsey, function(fromIndex) { var actual = lodashStable.map(falsey, function(fromIndex) {
return _.indexOf(array, 1, fromIndex); return func(array, resolve(1), fromIndex);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should coerce `fromIndex` to an integer', function(assert) { QUnit.test('`_.' + methodName + '` should coerce `fromIndex` to an integer', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.indexOf(array, 2, 1.2), 1); assert.strictEqual(func(array, resolve(2), 1.2), 1);
}); });
}()); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -13114,24 +13116,26 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.lastIndexOf'); QUnit.module('lodash.findLastIndex and lodash.lastIndexOf');
(function() { lodashStable.each(['findLastIndex', 'lastIndexOf'], function(methodName) {
var array = [1, 2, 3, 1, 2, 3]; var array = [1, 2, 3, 1, 2, 3],
func = _[methodName],
resolve = methodName == 'findLastIndex' ? lodashStable.curry(lodashStable.eq) : identity;
QUnit.test('should return the index of the last matched value', function(assert) { QUnit.test('`_.' + methodName + '` should return the index of the last matched value', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.lastIndexOf(array, 3), 5); assert.strictEqual(func(array, resolve(3)), 5);
}); });
QUnit.test('should work with a positive `fromIndex`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a positive `fromIndex`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.lastIndexOf(array, 1, 2), 0); assert.strictEqual(func(array, resolve(1), 2), 0);
}); });
QUnit.test('should work with `fromIndex` >= `array.length`', function(assert) { QUnit.test('`_.' + methodName + '` should work with `fromIndex` >= `array.length`', function(assert) {
assert.expect(1); assert.expect(1);
var values = [6, 8, Math.pow(2, 32), Infinity], var values = [6, 8, Math.pow(2, 32), Infinity],
@@ -13139,35 +13143,35 @@
var actual = lodashStable.map(values, function(fromIndex) { var actual = lodashStable.map(values, function(fromIndex) {
return [ return [
_.lastIndexOf(array, undefined, fromIndex), func(array, resolve(undefined), fromIndex),
_.lastIndexOf(array, 1, fromIndex), func(array, resolve(1), fromIndex),
_.lastIndexOf(array, '', fromIndex) func(array, resolve(''), fromIndex)
]; ];
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work with a negative `fromIndex`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a negative `fromIndex`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.lastIndexOf(array, 2, -3), 1); assert.strictEqual(func(array, resolve(2), -3), 1);
}); });
QUnit.test('should work with a negative `fromIndex` <= `-array.length`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a negative `fromIndex` <= `-array.length`', function(assert) {
assert.expect(1); assert.expect(1);
var values = [-6, -8, -Infinity], var values = [-6, -8, -Infinity],
expected = lodashStable.map(values, alwaysZero); expected = lodashStable.map(values, alwaysZero);
var actual = lodashStable.map(values, function(fromIndex) { var actual = lodashStable.map(values, function(fromIndex) {
return _.lastIndexOf(array, 1, fromIndex); return func(array, resolve(1), fromIndex);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should treat falsey `fromIndex` values correctly', function(assert) { QUnit.test('`_.' + methodName + '` should treat falsey `fromIndex` values correctly', function(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, function(value) { var expected = lodashStable.map(falsey, function(value) {
@@ -13175,18 +13179,18 @@
}); });
var actual = lodashStable.map(falsey, function(fromIndex) { var actual = lodashStable.map(falsey, function(fromIndex) {
return _.lastIndexOf(array, 3, fromIndex); return func(array, resolve(3), fromIndex);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should coerce `fromIndex` to an integer', function(assert) { QUnit.test('`_.' + methodName + '` should coerce `fromIndex` to an integer', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.lastIndexOf(array, 2, 4.2), 4); assert.strictEqual(func(array, resolve(2), 4.2), 4);
}); });
}()); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/