diff --git a/lodash.src.js b/lodash.src.js index e94dc25b7..bc725a40c 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1647,11 +1647,12 @@ * @returns {number} Returns the sum. */ function arraySum(array, iteratee) { - var length = array.length, + var index = -1, + length = array.length, result = 0; - while (length--) { - result += +iteratee(array[length]) || 0; + while (++index < length) { + result += +iteratee(array[index]) || 0; } return result; } @@ -1975,32 +1976,6 @@ 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. * @@ -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 * and `this` binding. @@ -3222,22 +3180,13 @@ * @returns {Function} Returns the new extremum function. */ function createExtremum(comparator, exValue) { - return function(collection, iteratee, guard) { - if (guard && isIterateeCall(collection, iteratee, guard)) { + return function(array, iteratee, guard) { + if (guard && isIterateeCall(array, iteratee, guard)) { iteratee = undefined; } - iteratee = getIteratee(iteratee); - if (iteratee.length == 1) { - collection = isArray(collection) ? collection : toIterable(collection); - if (!collection.length) { - return exValue; - } - var result = arrayExtremum(collection, iteratee, comparator, exValue); - if (result !== exValue) { - return result; - } - } - return baseExtremum(collection, iteratee, comparator, exValue); + return (array && array.length) + ? arrayExtremum(array, getIteratee(iteratee), comparator, exValue) + : exValue; }; } @@ -11301,14 +11250,12 @@ var round = createRound('round'); /** - * Gets the sum of the values in `collection`. + * Gets the sum of the values in `array`. * * @static * @memberOf _ * @category Math - * @param {Array|Object|string} collection The collection 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`. + * @param {Array} array The array to iterate over. * @returns {number} Returns the sum. * @example * @@ -11317,6 +11264,24 @@ * * _.sum({ 'a': 4, 'b': 6 }); * // => 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 = [ * { 'n': 4 }, @@ -11330,14 +11295,14 @@ * _.sum(objects, 'n'); * // => 10 */ - function sum(collection, iteratee, guard) { - if (guard && isIterateeCall(collection, iteratee, guard)) { + function sumBy(array, iteratee, guard) { + if (!(array && array.length)) { + return 0; + } + if (guard && isIterateeCall(array, iteratee, guard)) { iteratee = undefined; } - iteratee = getIteratee(iteratee); - return iteratee.length == 1 - ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) - : baseSum(collection, iteratee); + return arraySum(array, getIteratee(iteratee)); } /*------------------------------------------------------------------------*/ @@ -11562,6 +11527,7 @@ lodash.startCase = startCase; lodash.startsWith = startsWith; lodash.sum = sum; + lodash.sumBy = sumBy; lodash.template = template; lodash.trim = trim; lodash.trimLeft = trimLeft; diff --git a/test/test.js b/test/test.js index 326341a1f..db4ef127d 100644 --- a/test/test.js +++ b/test/test.js @@ -14550,9 +14550,7 @@ QUnit.module('lodash.sum'); (function() { - var array = [6, 4, 2], - object = { 'a': 2, 'b': 3, 'c': 1 }, - objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }]; + var array = [6, 4, 2]; test('should return the sum of an array of numbers', 1, function() { strictEqual(_.sum(array), 12); @@ -14571,51 +14569,43 @@ test('should coerce values to numbers and `NaN` to `0`', 1, function() { strictEqual(_.sum(['1', NaN, '2']), 3); }); + }()); - test('should iterate an object', 1, function() { - strictEqual(_.sum(object), 6); - }); + /*--------------------------------------------------------------------------*/ - test('should iterate a string', 2, function() { - _.each(['123', Object('123')], function(value) { - strictEqual(_.sum(value), 6); - }); - }); + QUnit.module('lodash.sumBy'); + + (function() { + var array = [6, 4, 2], + objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }]; test('should work with an `iteratee` argument', 1, function() { - var actual = _.sum(objects, function(object) { + var actual = _.sumBy(objects, function(object) { return object.a; }); deepEqual(actual, 6); }); - test('should provide the correct `iteratee` arguments', 2, function() { + test('should provide the correct `iteratee` arguments', 1, function() { var args; - _.sum(array, function() { + _.sumBy(array, function() { args || (args = slice.call(arguments)); }); - deepEqual(args, [6, 0, array]); - - args = null; - _.sum(object, function() { - args || (args = slice.call(arguments)); - }); - - deepEqual(args, [2, 'a', object]); + deepEqual(args, [6]); }); test('should work with a "_.property" style `iteratee`', 2, function() { var arrays = [[2], [3], [1]]; - strictEqual(_.sum(arrays, 0), 6); - strictEqual(_.sum(objects, 'a'), 6); + strictEqual(_.sumBy(arrays, 0), 6); + strictEqual(_.sumBy(objects, 'a'), 6); }); test('should perform basic sum when used as an iteratee for methods like `_.map`', 1, function() { - var actual = _.map([array, object], _.sum); - deepEqual(actual, [12, 6]); + var actual = _.map([array, array], _.sumBy); + deepEqual(actual, [12, 12]); }); }()); @@ -17538,7 +17528,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 208, function() { + test('should accept falsey arguments', 209, function() { var emptyArrays = _.map(falsey, _.constant([])); _.each(acceptFalsey, function(methodName) {