mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 02:47:50 +00:00
Split out _.sortedIndex and _.sortedLastIndex into _.sortedIndexBy and _.sortedLastIndexBy.
This commit is contained in:
committed by
John-David Dalton
parent
bc7cabde4e
commit
41f248f54d
@@ -5044,10 +5044,30 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses a binary search to determine the lowest index at which `value` should
|
* Uses a binary search to determine the lowest index at which `value` should
|
||||||
* be inserted into `array` in order to maintain its sort order. If an iteratee
|
* be inserted into `array` in order to maintain its sort order.
|
||||||
* function is provided it's invoked for `value` and each element of `array`
|
*
|
||||||
* to compute their sort ranking. The iteratee is invoked with one argument:
|
* @static
|
||||||
* (value).
|
* @memberOf _
|
||||||
|
* @category Array
|
||||||
|
* @param {Array} array The sorted array to inspect.
|
||||||
|
* @param {*} value The value to evaluate.
|
||||||
|
* @returns {number} Returns the index at which `value` should be inserted into `array`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.sortedIndex([30, 50], 40);
|
||||||
|
* // => 1
|
||||||
|
*
|
||||||
|
* _.sortedIndex([4, 5], 4);
|
||||||
|
* // => 0
|
||||||
|
*/
|
||||||
|
function sortedIndex(array, value) {
|
||||||
|
return binaryIndex(array, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is like `_.sortedIndex` except that it accepts an iteratee
|
||||||
|
* which is invoked for `value` and each element of `array` to compute their
|
||||||
|
* sort ranking. The iteratee is invoked with one argument: (value).
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
@@ -5058,27 +5078,17 @@
|
|||||||
* @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`.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* _.sortedIndex([30, 50], 40);
|
|
||||||
* // => 1
|
|
||||||
*
|
|
||||||
* _.sortedIndex([4, 4, 5, 5], 5);
|
|
||||||
* // => 2
|
|
||||||
*
|
|
||||||
* var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 };
|
* var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 };
|
||||||
*
|
*
|
||||||
* // using an iteratee function
|
* _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict));
|
||||||
* _.sortedIndex(['thirty', 'fifty'], 'forty', _.propertyOf(dict));
|
|
||||||
* // => 1
|
* // => 1
|
||||||
*
|
*
|
||||||
* // using the `_.property` callback shorthand
|
* // using the `_.property` callback shorthand
|
||||||
* _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
|
* _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
|
||||||
* // => 1
|
* // => 0
|
||||||
*/
|
*/
|
||||||
function sortedIndex(array, value, iteratee) {
|
function sortedIndexBy(array, value, iteratee) {
|
||||||
var toIteratee = getIteratee();
|
return binaryIndexBy(array, value, getIteratee(iteratee));
|
||||||
return (iteratee == null && toIteratee === baseIteratee)
|
|
||||||
? binaryIndex(array, value)
|
|
||||||
: binaryIndexBy(array, value, toIteratee(iteratee));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5091,18 +5101,36 @@
|
|||||||
* @category Array
|
* @category Array
|
||||||
* @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.
|
||||||
|
* @returns {number} Returns the index at which `value` should be inserted into `array`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.sortedLastIndex([4, 5], 4);
|
||||||
|
* // => 1
|
||||||
|
*/
|
||||||
|
function sortedLastIndex(array, value) {
|
||||||
|
return binaryIndex(array, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is like `_.sortedLastIndex` except that it accepts an iteratee
|
||||||
|
* which is invoked for `value` and each element of `array` to compute their
|
||||||
|
* sort ranking. The iteratee is invoked with one argument: (value).
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @category Array
|
||||||
|
* @param {Array} array The sorted array to inspect.
|
||||||
|
* @param {*} value The value to evaluate.
|
||||||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
|
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
|
||||||
* @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`.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* _.sortedLastIndex([4, 4, 5, 5], 5);
|
* // using the `_.property` callback shorthand
|
||||||
* // => 4
|
* _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
|
||||||
|
* // => 1
|
||||||
*/
|
*/
|
||||||
function sortedLastIndex(array, value, iteratee) {
|
function sortedLastIndexBy(array, value, iteratee) {
|
||||||
var toIteratee = getIteratee();
|
return binaryIndexBy(array, value, getIteratee(iteratee), true);
|
||||||
return (iteratee == null && toIteratee === baseIteratee)
|
|
||||||
? binaryIndex(array, value, true)
|
|
||||||
: binaryIndexBy(array, value, toIteratee(iteratee), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11526,7 +11554,9 @@
|
|||||||
lodash.snakeCase = snakeCase;
|
lodash.snakeCase = snakeCase;
|
||||||
lodash.some = some;
|
lodash.some = some;
|
||||||
lodash.sortedIndex = sortedIndex;
|
lodash.sortedIndex = sortedIndex;
|
||||||
|
lodash.sortedIndexBy = sortedIndexBy;
|
||||||
lodash.sortedLastIndex = sortedLastIndex;
|
lodash.sortedLastIndex = sortedLastIndex;
|
||||||
|
lodash.sortedLastIndexBy = sortedLastIndexBy;
|
||||||
lodash.startCase = startCase;
|
lodash.startCase = startCase;
|
||||||
lodash.startsWith = startsWith;
|
lodash.startsWith = startsWith;
|
||||||
lodash.sum = sum;
|
lodash.sum = sum;
|
||||||
|
|||||||
65
test/test.js
65
test/test.js
@@ -8739,12 +8739,12 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.sortedIndex` should use `_.iteratee` internally', 1, function() {
|
test('`_.sortedIndexBy` should use `_.iteratee` internally', 1, function() {
|
||||||
if (!isModularize) {
|
if (!isModularize) {
|
||||||
var objects = [{ 'a': 30 }, { 'a': 50 }];
|
var objects = [{ 'a': 30 }, { 'a': 50 }];
|
||||||
|
|
||||||
_.iteratee = getPropA;
|
_.iteratee = getPropA;
|
||||||
strictEqual(_.sortedIndex(objects, { 'a': 40 }), 1);
|
strictEqual(_.sortedIndexBy(objects, { 'a': 40 }), 1);
|
||||||
_.iteratee = iteratee;
|
_.iteratee = iteratee;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -8752,12 +8752,12 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.sortedLastIndex` should use `_.iteratee` internally', 1, function() {
|
test('`_.sortedLastIndexBy` should use `_.iteratee` internally', 1, function() {
|
||||||
if (!isModularize) {
|
if (!isModularize) {
|
||||||
var objects = [{ 'a': 30 }, { 'a': 50 }];
|
var objects = [{ 'a': 30 }, { 'a': 50 }];
|
||||||
|
|
||||||
_.iteratee = getPropA;
|
_.iteratee = getPropA;
|
||||||
strictEqual(_.sortedLastIndex(objects, { 'a': 40 }), 1);
|
strictEqual(_.sortedLastIndexBy(objects, { 'a': 40 }), 1);
|
||||||
_.iteratee = iteratee;
|
_.iteratee = iteratee;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -14323,13 +14323,12 @@
|
|||||||
QUnit.module('sortedIndex methods');
|
QUnit.module('sortedIndex methods');
|
||||||
|
|
||||||
_.each(['sortedIndex', 'sortedLastIndex'], function(methodName) {
|
_.each(['sortedIndex', 'sortedLastIndex'], function(methodName) {
|
||||||
var array = [30, 50],
|
var func = _[methodName],
|
||||||
func = _[methodName],
|
isSortedIndex = methodName == 'sortedIndex';
|
||||||
isSortedIndex = methodName == 'sortedIndex',
|
|
||||||
objects = [{ 'x': 30 }, { 'x': 50 }];
|
|
||||||
|
|
||||||
test('`_.' + methodName + '` should return the insert index', 1, function() {
|
test('`_.' + methodName + '` should return the insert index', 1, function() {
|
||||||
var values = [30, 40, 50],
|
var array = [30, 50],
|
||||||
|
values = [30, 40, 50],
|
||||||
expected = isSortedIndex ? [0, 1, 1] : [1, 1, 2];
|
expected = isSortedIndex ? [0, 1, 1] : [1, 1, 2];
|
||||||
|
|
||||||
var actual = _.map(values, function(value) {
|
var actual = _.map(values, function(value) {
|
||||||
@@ -14361,21 +14360,6 @@
|
|||||||
deepEqual(actual, expected);
|
deepEqual(actual, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` should provide the correct `iteratee` arguments', 1, function() {
|
|
||||||
var args;
|
|
||||||
|
|
||||||
func(array, 40, function() {
|
|
||||||
args || (args = slice.call(arguments));
|
|
||||||
});
|
|
||||||
|
|
||||||
deepEqual(args, [40]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('`_.' + methodName + '` should work with a "_.property" style `iteratee`', 1, function() {
|
|
||||||
var actual = func(objects, { 'x': 40 }, 'x');
|
|
||||||
strictEqual(actual, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('`_.' + methodName + '` should align with `_.sortBy`', 10, function() {
|
test('`_.' + methodName + '` should align with `_.sortBy`', 10, function() {
|
||||||
var expected = [1, '2', {}, null, undefined, NaN, NaN];
|
var expected = [1, '2', {}, null, undefined, NaN, NaN];
|
||||||
|
|
||||||
@@ -14390,6 +14374,32 @@
|
|||||||
strictEqual(func(expected, NaN), isSortedIndex ? 5 : 7);
|
strictEqual(func(expected, NaN), isSortedIndex ? 5 : 7);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
QUnit.module('sortedIndexBy methods');
|
||||||
|
|
||||||
|
_.each(['sortedIndexBy', 'sortedLastIndexBy'], function(methodName) {
|
||||||
|
var func = _[methodName],
|
||||||
|
isSortedIndexBy = methodName == 'sortedIndexBy';
|
||||||
|
|
||||||
|
test('`_.' + methodName + '` should provide the correct `iteratee` arguments', 1, function() {
|
||||||
|
var args;
|
||||||
|
|
||||||
|
func([30, 50], 40, function() {
|
||||||
|
args || (args = slice.call(arguments));
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(args, [40]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('`_.' + methodName + '` should work with a "_.property" style `iteratee`', 1, function() {
|
||||||
|
var objects = [{ 'x': 30 }, { 'x': 50 }],
|
||||||
|
actual = func(objects, { 'x': 40 }, 'x');
|
||||||
|
|
||||||
|
strictEqual(actual, 1);
|
||||||
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` should support arrays larger than `MAX_ARRAY_LENGTH / 2`', 12, function() {
|
test('`_.' + methodName + '` should support arrays larger than `MAX_ARRAY_LENGTH / 2`', 12, function() {
|
||||||
_.each([Math.ceil(MAX_ARRAY_LENGTH / 2), MAX_ARRAY_LENGTH], function(length) {
|
_.each([Math.ceil(MAX_ARRAY_LENGTH / 2), MAX_ARRAY_LENGTH], function(length) {
|
||||||
@@ -14402,7 +14412,7 @@
|
|||||||
var steps = 0,
|
var steps = 0,
|
||||||
actual = func(array, value, function(value) { steps++; return value; });
|
actual = func(array, value, function(value) { steps++; return value; });
|
||||||
|
|
||||||
var expected = (isSortedIndex ? !_.isNaN(value) : _.isFinite(value))
|
var expected = (isSortedIndexBy ? !_.isNaN(value) : _.isFinite(value))
|
||||||
? 0
|
? 0
|
||||||
: Math.min(length, MAX_ARRAY_INDEX);
|
: Math.min(length, MAX_ARRAY_INDEX);
|
||||||
|
|
||||||
@@ -17347,7 +17357,7 @@
|
|||||||
var args = arguments,
|
var args = arguments,
|
||||||
array = [1, 2, 3, 4, 5, 6];
|
array = [1, 2, 3, 4, 5, 6];
|
||||||
|
|
||||||
test('should work with `arguments` objects', 27, function() {
|
test('should work with `arguments` objects', 28, function() {
|
||||||
function message(methodName) {
|
function message(methodName) {
|
||||||
return '`_.' + methodName + '` should work with `arguments` objects';
|
return '`_.' + methodName + '` should work with `arguments` objects';
|
||||||
}
|
}
|
||||||
@@ -17374,6 +17384,7 @@
|
|||||||
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(args, 6), 5, message('sortedIndex'));
|
||||||
|
deepEqual(_.sortedLastIndex(args, 6), 5, message('sortedLastIndex'));
|
||||||
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'));
|
||||||
@@ -17514,7 +17525,7 @@
|
|||||||
|
|
||||||
var acceptFalsey = _.difference(allMethods, rejectFalsey);
|
var acceptFalsey = _.difference(allMethods, rejectFalsey);
|
||||||
|
|
||||||
test('should accept falsey arguments', 209, function() {
|
test('should accept falsey arguments', 211, function() {
|
||||||
var emptyArrays = _.map(falsey, _.constant([]));
|
var emptyArrays = _.map(falsey, _.constant([]));
|
||||||
|
|
||||||
_.each(acceptFalsey, function(methodName) {
|
_.each(acceptFalsey, function(methodName) {
|
||||||
|
|||||||
Reference in New Issue
Block a user