mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-09 10:27:49 +00:00
Split _.max and _.min out into _.maxBy and _.minBy.
This commit is contained in:
committed by
John-David Dalton
parent
cb94b03e3e
commit
86b19f742c
104
lodash.src.js
104
lodash.src.js
@@ -1987,7 +1987,7 @@
|
|||||||
* @param {*} exValue The initial extremum value.
|
* @param {*} exValue The initial extremum value.
|
||||||
* @returns {*} Returns the extremum value.
|
* @returns {*} Returns the extremum value.
|
||||||
*/
|
*/
|
||||||
function baseExtremum(collection, iteratee, comparator, exValue) {
|
function baseExtremumBy(collection, iteratee, comparator, exValue) {
|
||||||
var computed = exValue,
|
var computed = exValue,
|
||||||
result = computed;
|
result = computed;
|
||||||
|
|
||||||
@@ -3302,11 +3302,24 @@
|
|||||||
* Creates a `_.max` or `_.min` function.
|
* Creates a `_.max` or `_.min` function.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
|
* @param {Function} extremumBy The function used to get the extremum value.
|
||||||
|
* @returns {Function} Returns the new extremum function.
|
||||||
|
*/
|
||||||
|
function createExtremum(extremumBy) {
|
||||||
|
return function(collection) {
|
||||||
|
return extremumBy(collection, identity);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a `_.maxBy` or `_.minBy` function.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
* @param {Function} comparator The function used to compare values.
|
* @param {Function} comparator The function used to compare values.
|
||||||
* @param {*} exValue The initial extremum value.
|
* @param {*} exValue The initial extremum value.
|
||||||
* @returns {Function} Returns the new extremum function.
|
* @returns {Function} Returns the new extremum function.
|
||||||
*/
|
*/
|
||||||
function createExtremum(comparator, exValue) {
|
function createExtremumBy(comparator, exValue) {
|
||||||
return function(collection, iteratee, guard) {
|
return function(collection, iteratee, guard) {
|
||||||
if (guard && isIterateeCall(collection, iteratee, guard)) {
|
if (guard && isIterateeCall(collection, iteratee, guard)) {
|
||||||
iteratee = undefined;
|
iteratee = undefined;
|
||||||
@@ -3314,12 +3327,15 @@
|
|||||||
iteratee = getIteratee(iteratee);
|
iteratee = getIteratee(iteratee);
|
||||||
if (iteratee.length == 1) {
|
if (iteratee.length == 1) {
|
||||||
collection = isArray(collection) ? collection : toIterable(collection);
|
collection = isArray(collection) ? collection : toIterable(collection);
|
||||||
|
if (!collection.length) {
|
||||||
|
return exValue;
|
||||||
|
}
|
||||||
var result = arrayExtremum(collection, iteratee, comparator, exValue);
|
var result = arrayExtremum(collection, iteratee, comparator, exValue);
|
||||||
if (!(collection.length && result === exValue)) {
|
if (result !== exValue) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return baseExtremum(collection, iteratee, comparator, exValue);
|
return baseExtremumBy(collection, iteratee, comparator, exValue);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11291,10 +11307,10 @@
|
|||||||
var floor = createRound('floor');
|
var floor = createRound('floor');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the maximum value of `collection`. If `collection` is empty or falsey
|
* This method is like `_.max` except that it accepts an iteratee which is
|
||||||
* `-Infinity` is returned. If an iteratee function is provided it's invoked
|
* invoked for each value in `collection` to generate the criterion by which
|
||||||
* for each value in `collection` to generate the criterion by which the value
|
* the value is ranked. The iteratee is invoked with three arguments:
|
||||||
* is ranked. The iteratee is invoked with three arguments: (value, index, collection).
|
* (value, index, collection).
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
@@ -11304,31 +11320,44 @@
|
|||||||
* @returns {*} Returns the maximum value.
|
* @returns {*} Returns the maximum value.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* _.max([4, 2, 8, 6]);
|
|
||||||
* // => 8
|
|
||||||
*
|
|
||||||
* _.max([]);
|
|
||||||
* // => -Infinity
|
|
||||||
*
|
|
||||||
* var users = [
|
* var users = [
|
||||||
* { 'user': 'barney', 'age': 36 },
|
* { 'user': 'barney', 'age': 36 },
|
||||||
* { 'user': 'fred', 'age': 40 }
|
* { 'user': 'fred', 'age': 40 }
|
||||||
* ];
|
* ];
|
||||||
*
|
*
|
||||||
* _.max(users, function(o) { return o.age; });
|
* _.maxBy(users, function(o) { return o.age; });
|
||||||
* // => { 'user': 'fred', 'age': 40 }
|
* // => { 'user': 'fred', 'age': 40 }
|
||||||
*
|
*
|
||||||
* // using the `_.property` callback shorthand
|
* // using the `_.property` callback shorthand
|
||||||
* _.max(users, 'age');
|
* _.maxBy(users, 'age');
|
||||||
* // => { 'user': 'fred', 'age': 40 }
|
* // => { 'user': 'fred', 'age': 40 }
|
||||||
*/
|
*/
|
||||||
var max = createExtremum(gt, NEGATIVE_INFINITY);
|
var maxBy = createExtremumBy(gt, NEGATIVE_INFINITY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the minimum value of `collection`. If `collection` is empty or falsey
|
* Gets the maximum value of `collection`. If `collection` is empty or falsey
|
||||||
* `Infinity` is returned. If an iteratee function is provided it's invoked
|
* `-Infinity` is returned.
|
||||||
* for each value in `collection` to generate the criterion by which the value
|
*
|
||||||
* is ranked. The iteratee is invoked with three arguments: (value, index, collection).
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @category Math
|
||||||
|
* @param {Array|Object|string} collection The collection to iterate over.
|
||||||
|
* @returns {*} Returns the maximum value.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.max([4, 2, 8, 6]);
|
||||||
|
* // => 8
|
||||||
|
*
|
||||||
|
* _.max([]);
|
||||||
|
* // => -Infinity
|
||||||
|
*/
|
||||||
|
var max = createExtremum(maxBy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is like `_.min` except that it accepts an iteratee which is
|
||||||
|
* invoked for each value in `collection` to generate the criterion by which
|
||||||
|
* the value is ranked. The iteratee is invoked with three arguments:
|
||||||
|
* (value, index, collection).
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
@@ -11338,25 +11367,38 @@
|
|||||||
* @returns {*} Returns the minimum value.
|
* @returns {*} Returns the minimum value.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* _.min([4, 2, 8, 6]);
|
|
||||||
* // => 2
|
|
||||||
*
|
|
||||||
* _.min([]);
|
|
||||||
* // => Infinity
|
|
||||||
*
|
|
||||||
* var users = [
|
* var users = [
|
||||||
* { 'user': 'barney', 'age': 36 },
|
* { 'user': 'barney', 'age': 36 },
|
||||||
* { 'user': 'fred', 'age': 40 }
|
* { 'user': 'fred', 'age': 40 }
|
||||||
* ];
|
* ];
|
||||||
*
|
*
|
||||||
* _.min(users, function(o) { return o.age; });
|
* _.minBy(users, function(o) { return o.age; });
|
||||||
* // => { 'user': 'barney', 'age': 36 }
|
* // => { 'user': 'barney', 'age': 36 }
|
||||||
*
|
*
|
||||||
* // using the `_.property` callback shorthand
|
* // using the `_.property` callback shorthand
|
||||||
* _.min(users, 'age');
|
* _.minBy(users, 'age');
|
||||||
* // => { 'user': 'barney', 'age': 36 }
|
* // => { 'user': 'barney', 'age': 36 }
|
||||||
*/
|
*/
|
||||||
var min = createExtremum(lt, POSITIVE_INFINITY);
|
var minBy = createExtremumBy(lt, POSITIVE_INFINITY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum value of `collection`. If `collection` is empty or falsey
|
||||||
|
* `Infinity` is returned.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @category Math
|
||||||
|
* @param {Array|Object|string} collection The collection to iterate over.
|
||||||
|
* @returns {*} Returns the minimum value.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.min([4, 2, 8, 6]);
|
||||||
|
* // => 2
|
||||||
|
*
|
||||||
|
* _.min([]);
|
||||||
|
* // => Infinity
|
||||||
|
*/
|
||||||
|
var min = createExtremum(minBy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates `n` rounded to `precision`.
|
* Calculates `n` rounded to `precision`.
|
||||||
@@ -11616,7 +11658,9 @@
|
|||||||
lodash.lt = lt;
|
lodash.lt = lt;
|
||||||
lodash.lte = lte;
|
lodash.lte = lte;
|
||||||
lodash.max = max;
|
lodash.max = max;
|
||||||
|
lodash.maxBy = maxBy;
|
||||||
lodash.min = min;
|
lodash.min = min;
|
||||||
|
lodash.minBy = minBy;
|
||||||
lodash.noConflict = noConflict;
|
lodash.noConflict = noConflict;
|
||||||
lodash.noop = noop;
|
lodash.noop = noop;
|
||||||
lodash.now = now;
|
lodash.now = now;
|
||||||
|
|||||||
120
test/test.js
120
test/test.js
@@ -4724,8 +4724,8 @@
|
|||||||
'map',
|
'map',
|
||||||
'mapKeys',
|
'mapKeys',
|
||||||
'mapValues',
|
'mapValues',
|
||||||
'max',
|
'maxBy',
|
||||||
'min',
|
'minBy',
|
||||||
'omit',
|
'omit',
|
||||||
'partition',
|
'partition',
|
||||||
'pick',
|
'pick',
|
||||||
@@ -4750,8 +4750,8 @@
|
|||||||
'groupBy',
|
'groupBy',
|
||||||
'indexBy',
|
'indexBy',
|
||||||
'map',
|
'map',
|
||||||
'max',
|
'maxBy',
|
||||||
'min',
|
'minBy',
|
||||||
'partition',
|
'partition',
|
||||||
'reduce',
|
'reduce',
|
||||||
'reduceRight',
|
'reduceRight',
|
||||||
@@ -4813,7 +4813,9 @@
|
|||||||
'forOwn',
|
'forOwn',
|
||||||
'forOwnRight',
|
'forOwnRight',
|
||||||
'max',
|
'max',
|
||||||
|
'maxBy',
|
||||||
'min',
|
'min',
|
||||||
|
'minBy',
|
||||||
'some'
|
'some'
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -8607,10 +8609,10 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.max` should use `_.iteratee` internally', 1, function() {
|
test('`_.maxBy` should use `_.iteratee` internally', 1, function() {
|
||||||
if (!isModularize) {
|
if (!isModularize) {
|
||||||
_.iteratee = getPropB;
|
_.iteratee = getPropB;
|
||||||
deepEqual(_.max(objects), objects[2]);
|
deepEqual(_.maxBy(objects), objects[2]);
|
||||||
_.iteratee = iteratee;
|
_.iteratee = iteratee;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -8618,10 +8620,10 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.min` should use `_.iteratee` internally', 1, function() {
|
test('`_.minBy` should use `_.iteratee` internally', 1, function() {
|
||||||
if (!isModularize) {
|
if (!isModularize) {
|
||||||
_.iteratee = getPropB;
|
_.iteratee = getPropB;
|
||||||
deepEqual(_.min(objects), objects[0]);
|
deepEqual(_.minBy(objects), objects[0]);
|
||||||
_.iteratee = iteratee;
|
_.iteratee = iteratee;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -10833,10 +10835,10 @@
|
|||||||
|
|
||||||
QUnit.module('extremum methods');
|
QUnit.module('extremum methods');
|
||||||
|
|
||||||
_.each(['max', 'min'], function(methodName) {
|
_.each(['max', 'maxBy', 'min', 'minBy'], function(methodName) {
|
||||||
var array = [1, 2, 3],
|
var array = [1, 2, 3],
|
||||||
func = _[methodName],
|
func = _[methodName],
|
||||||
isMax = methodName == 'max';
|
isMax = /^max/.test(methodName);
|
||||||
|
|
||||||
test('`_.' + methodName + '` should work with Date objects', 1, function() {
|
test('`_.' + methodName + '` should work with Date objects', 1, function() {
|
||||||
var curr = new Date,
|
var curr = new Date,
|
||||||
@@ -10845,63 +10847,6 @@
|
|||||||
strictEqual(func([curr, past]), isMax ? curr : past);
|
strictEqual(func([curr, past]), isMax ? curr : past);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` should work with an `iteratee` argument', 1, function() {
|
|
||||||
var actual = func(array, function(num) {
|
|
||||||
return -num;
|
|
||||||
});
|
|
||||||
|
|
||||||
strictEqual(actual, isMax ? 1 : 3);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an array', 1, function() {
|
|
||||||
var args;
|
|
||||||
|
|
||||||
func(array, function() {
|
|
||||||
args || (args = slice.call(arguments));
|
|
||||||
});
|
|
||||||
|
|
||||||
deepEqual(args, [1, 0, array]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an object', 1, function() {
|
|
||||||
var args,
|
|
||||||
object = { 'a': 1, 'b': 2 },
|
|
||||||
firstKey = _.first(_.keys(object));
|
|
||||||
|
|
||||||
var expected = firstKey == 'a'
|
|
||||||
? [1, 'a', object]
|
|
||||||
: [2, 'b', object];
|
|
||||||
|
|
||||||
func(object, function() {
|
|
||||||
args || (args = slice.call(arguments));
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
deepEqual(args, expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should work with a "_.property" style `iteratee`', 2, function() {
|
|
||||||
var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }],
|
|
||||||
actual = func(objects, 'a');
|
|
||||||
|
|
||||||
deepEqual(actual, objects[isMax ? 1 : 2]);
|
|
||||||
|
|
||||||
var arrays = [[2], [3], [1]];
|
|
||||||
actual = func(arrays, 0);
|
|
||||||
|
|
||||||
deepEqual(actual, arrays[isMax ? 1 : 2]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('`_.' + methodName + '` should work when `iteratee` returns +/-Infinity', 1, function() {
|
|
||||||
var value = isMax ? -Infinity : Infinity,
|
|
||||||
object = { 'a': value };
|
|
||||||
|
|
||||||
var actual = func([object, { 'a': value }], function(object) {
|
|
||||||
return object.a;
|
|
||||||
});
|
|
||||||
|
|
||||||
strictEqual(actual, object);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('`_.' + methodName + '` should iterate an object', 1, function() {
|
test('`_.' + methodName + '` should iterate an object', 1, function() {
|
||||||
var actual = func({ 'a': 1, 'b': 2, 'c': 3 });
|
var actual = func({ 'a': 1, 'b': 2, 'c': 3 });
|
||||||
strictEqual(actual, isMax ? 3 : 1);
|
strictEqual(actual, isMax ? 3 : 1);
|
||||||
@@ -10933,6 +10878,43 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_.each(['maxBy', 'minBy'], function(methodName) {
|
||||||
|
var array = [1, 2, 3],
|
||||||
|
func = _[methodName],
|
||||||
|
isMax = methodName == 'maxBy';
|
||||||
|
|
||||||
|
test('`_.' + methodName + '` should work with an `iteratee` argument', 1, function() {
|
||||||
|
var actual = func(array, function(num) {
|
||||||
|
return -num;
|
||||||
|
});
|
||||||
|
|
||||||
|
strictEqual(actual, isMax ? 1 : 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work with a "_.property" style `iteratee`', 2, function() {
|
||||||
|
var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }],
|
||||||
|
actual = func(objects, 'a');
|
||||||
|
|
||||||
|
deepEqual(actual, objects[isMax ? 1 : 2]);
|
||||||
|
|
||||||
|
var arrays = [[2], [3], [1]];
|
||||||
|
actual = func(arrays, 0);
|
||||||
|
|
||||||
|
deepEqual(actual, arrays[isMax ? 1 : 2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('`_.' + methodName + '` should work when `iteratee` returns +/-Infinity', 1, function() {
|
||||||
|
var value = isMax ? -Infinity : Infinity,
|
||||||
|
object = { 'a': value };
|
||||||
|
|
||||||
|
var actual = func([object, { 'a': value }], function(object) {
|
||||||
|
return object.a;
|
||||||
|
});
|
||||||
|
|
||||||
|
strictEqual(actual, object);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
QUnit.module('lodash.mixin');
|
QUnit.module('lodash.mixin');
|
||||||
@@ -17318,7 +17300,9 @@
|
|||||||
'join',
|
'join',
|
||||||
'last',
|
'last',
|
||||||
'max',
|
'max',
|
||||||
|
'maxBy',
|
||||||
'min',
|
'min',
|
||||||
|
'minBy',
|
||||||
'parseInt',
|
'parseInt',
|
||||||
'pop',
|
'pop',
|
||||||
'shift',
|
'shift',
|
||||||
@@ -17531,7 +17515,7 @@
|
|||||||
|
|
||||||
var acceptFalsey = _.difference(allMethods, rejectFalsey);
|
var acceptFalsey = _.difference(allMethods, rejectFalsey);
|
||||||
|
|
||||||
test('should accept falsey arguments', 205, function() {
|
test('should accept falsey arguments', 207, 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