Add _.sumBy.

This commit is contained in:
jdalton
2015-07-05 23:18:10 -07:00
committed by John-David Dalton
parent 83ac168664
commit 340a6d195f
2 changed files with 53 additions and 97 deletions

View File

@@ -1647,11 +1647,12 @@
* @returns {number} Returns the sum. * @returns {number} Returns the sum.
*/ */
function arraySum(array, iteratee) { function arraySum(array, iteratee) {
var length = array.length, var index = -1,
length = array.length,
result = 0; result = 0;
while (length--) { while (++index < length) {
result += +iteratee(array[length]) || 0; result += +iteratee(array[index]) || 0;
} }
return result; return result;
} }
@@ -1975,32 +1976,6 @@
return result; return result;
} }
/**
* Gets the extremum value of `collection` invoking `iteratee` for each value
* in `collection` to generate the criterion by which the value is ranked.
* The iteratee is invoked with three arguments: (value, index|key, collection).
*
* @private
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {Function} comparator The function used to compare values.
* @param {*} exValue The initial extremum value.
* @returns {*} Returns the extremum value.
*/
function baseExtremum(collection, iteratee, comparator, exValue) {
var computed = exValue,
result = computed;
baseEach(collection, function(value, index, collection) {
var current = +iteratee(value, index, collection);
if (comparator(current, computed) || (current === exValue && current === result)) {
computed = current;
result = value;
}
});
return result;
}
/** /**
* The base implementation of `_.fill` without an iteratee call guard. * The base implementation of `_.fill` without an iteratee call guard.
* *
@@ -2729,23 +2704,6 @@
}); });
} }
/**
* The base implementation of `_.sum` without support for callback shorthands
* and `this` binding.
*
* @private
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {number} Returns the sum.
*/
function baseSum(collection, iteratee) {
var result = 0;
baseEach(collection, function(value, index, collection) {
result += +iteratee(value, index, collection) || 0;
});
return result;
}
/** /**
* The base implementation of `_.uniq` without support for callback shorthands * The base implementation of `_.uniq` without support for callback shorthands
* and `this` binding. * and `this` binding.
@@ -3222,22 +3180,13 @@
* @returns {Function} Returns the new extremum function. * @returns {Function} Returns the new extremum function.
*/ */
function createExtremum(comparator, exValue) { function createExtremum(comparator, exValue) {
return function(collection, iteratee, guard) { return function(array, iteratee, guard) {
if (guard && isIterateeCall(collection, iteratee, guard)) { if (guard && isIterateeCall(array, iteratee, guard)) {
iteratee = undefined; iteratee = undefined;
} }
iteratee = getIteratee(iteratee); return (array && array.length)
if (iteratee.length == 1) { ? arrayExtremum(array, getIteratee(iteratee), comparator, exValue)
collection = isArray(collection) ? collection : toIterable(collection); : exValue;
if (!collection.length) {
return exValue;
}
var result = arrayExtremum(collection, iteratee, comparator, exValue);
if (result !== exValue) {
return result;
}
}
return baseExtremum(collection, iteratee, comparator, exValue);
}; };
} }
@@ -11301,14 +11250,12 @@
var round = createRound('round'); var round = createRound('round');
/** /**
* Gets the sum of the values in `collection`. * Gets the sum of the values in `array`.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Math * @category Math
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array} array The array to iterate over.
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
* @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
* @returns {number} Returns the sum. * @returns {number} Returns the sum.
* @example * @example
* *
@@ -11317,6 +11264,24 @@
* *
* _.sum({ 'a': 4, 'b': 6 }); * _.sum({ 'a': 4, 'b': 6 });
* // => 10 * // => 10
*/
function sum(array) {
return sumBy(array, identity);
}
/**
* This method is like `_.sum` except that it accepts an iteratee which is
* invoked for each element in `array` to generate the value to be summed.
* The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @category Math
* @param {Array} array The array to iterate over.
* @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
* @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
* @returns {number} Returns the sum.
* @example
* *
* var objects = [ * var objects = [
* { 'n': 4 }, * { 'n': 4 },
@@ -11330,14 +11295,14 @@
* _.sum(objects, 'n'); * _.sum(objects, 'n');
* // => 10 * // => 10
*/ */
function sum(collection, iteratee, guard) { function sumBy(array, iteratee, guard) {
if (guard && isIterateeCall(collection, iteratee, guard)) { if (!(array && array.length)) {
return 0;
}
if (guard && isIterateeCall(array, iteratee, guard)) {
iteratee = undefined; iteratee = undefined;
} }
iteratee = getIteratee(iteratee); return arraySum(array, getIteratee(iteratee));
return iteratee.length == 1
? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee)
: baseSum(collection, iteratee);
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@@ -11562,6 +11527,7 @@
lodash.startCase = startCase; lodash.startCase = startCase;
lodash.startsWith = startsWith; lodash.startsWith = startsWith;
lodash.sum = sum; lodash.sum = sum;
lodash.sumBy = sumBy;
lodash.template = template; lodash.template = template;
lodash.trim = trim; lodash.trim = trim;
lodash.trimLeft = trimLeft; lodash.trimLeft = trimLeft;

View File

@@ -14550,9 +14550,7 @@
QUnit.module('lodash.sum'); QUnit.module('lodash.sum');
(function() { (function() {
var array = [6, 4, 2], var array = [6, 4, 2];
object = { 'a': 2, 'b': 3, 'c': 1 },
objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
test('should return the sum of an array of numbers', 1, function() { test('should return the sum of an array of numbers', 1, function() {
strictEqual(_.sum(array), 12); strictEqual(_.sum(array), 12);
@@ -14571,51 +14569,43 @@
test('should coerce values to numbers and `NaN` to `0`', 1, function() { test('should coerce values to numbers and `NaN` to `0`', 1, function() {
strictEqual(_.sum(['1', NaN, '2']), 3); strictEqual(_.sum(['1', NaN, '2']), 3);
}); });
}());
test('should iterate an object', 1, function() { /*--------------------------------------------------------------------------*/
strictEqual(_.sum(object), 6);
});
test('should iterate a string', 2, function() { QUnit.module('lodash.sumBy');
_.each(['123', Object('123')], function(value) {
strictEqual(_.sum(value), 6); (function() {
}); var array = [6, 4, 2],
}); objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
test('should work with an `iteratee` argument', 1, function() { test('should work with an `iteratee` argument', 1, function() {
var actual = _.sum(objects, function(object) { var actual = _.sumBy(objects, function(object) {
return object.a; return object.a;
}); });
deepEqual(actual, 6); deepEqual(actual, 6);
}); });
test('should provide the correct `iteratee` arguments', 2, function() { test('should provide the correct `iteratee` arguments', 1, function() {
var args; var args;
_.sum(array, function() { _.sumBy(array, function() {
args || (args = slice.call(arguments)); args || (args = slice.call(arguments));
}); });
deepEqual(args, [6, 0, array]); deepEqual(args, [6]);
args = null;
_.sum(object, function() {
args || (args = slice.call(arguments));
});
deepEqual(args, [2, 'a', object]);
}); });
test('should work with a "_.property" style `iteratee`', 2, function() { test('should work with a "_.property" style `iteratee`', 2, function() {
var arrays = [[2], [3], [1]]; var arrays = [[2], [3], [1]];
strictEqual(_.sum(arrays, 0), 6); strictEqual(_.sumBy(arrays, 0), 6);
strictEqual(_.sum(objects, 'a'), 6); strictEqual(_.sumBy(objects, 'a'), 6);
}); });
test('should perform basic sum when used as an iteratee for methods like `_.map`', 1, function() { test('should perform basic sum when used as an iteratee for methods like `_.map`', 1, function() {
var actual = _.map([array, object], _.sum); var actual = _.map([array, array], _.sumBy);
deepEqual(actual, [12, 6]); deepEqual(actual, [12, 12]);
}); });
}()); }());
@@ -17538,7 +17528,7 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey); var acceptFalsey = _.difference(allMethods, rejectFalsey);
test('should accept falsey arguments', 208, function() { test('should accept falsey arguments', 209, function() {
var emptyArrays = _.map(falsey, _.constant([])); var emptyArrays = _.map(falsey, _.constant([]));
_.each(acceptFalsey, function(methodName) { _.each(acceptFalsey, function(methodName) {