From 9827f876112c6ee189e3e7655d50900f6f44334f Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Thu, 15 Jul 2010 09:50:55 -0400 Subject: [PATCH] (breaking change) moving _.reduce's method signature to that of ECMA5. _.reduce(obj, iterator, memo). Updated tests and docs. --- index.html | 12 ++++++------ test/chaining.js | 4 ++-- test/collections.js | 10 +++++----- underscore.js | 24 +++++++++++++++--------- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/index.html b/index.html index 4db208a51..4cbad8700 100644 --- a/index.html +++ b/index.html @@ -216,10 +216,10 @@ var lyrics = [ _(lyrics).chain() .map(function(line) { return line.words.split(' '); }) .flatten() - .reduce({}, function(counts, word) { + .reduce(function(counts, word) { counts[word] = (counts[word] || 0) + 1; return counts; -}).value(); +}, {}).value(); => {lumberjack : 2, all : 4, night : 2 ... } @@ -261,7 +261,7 @@ _.map([1, 2, 3], function(num){ return num * 3 }); => [3, 6, 9]

- reduce_.reduce(list, memo, iterator, [context]) + reduce_.reduce(list, iterator, memo, [context]) Aliases: inject, foldl
Also known as inject and foldl, reduce boils down a @@ -270,12 +270,12 @@ _.map([1, 2, 3], function(num){ return num * 3 }); iterator.

-var sum = _.reduce([1, 2, 3], 0, function(memo, num){ return memo + num });
+var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num }, 0);
 => 6
 

- reduceRight_.reduceRight(list, memo, iterator, [context]) + reduceRight_.reduceRight(list, iterator, memo, [context]) Alias: foldr
The right-associative version of reduce. Delegates to the @@ -285,7 +285,7 @@ var sum = _.reduce([1, 2, 3], 0, function(memo, num){ return memo + num });

 var list = [[0, 1], [2, 3], [4, 5]];
-var flat = _.reduceRight(list, [], function(a, b) { return a.concat(b); });
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
 => [4, 5, 2, 3, 0, 1]
 
diff --git a/test/chaining.js b/test/chaining.js index 55f0c8c0d..e633ba5ad 100644 --- a/test/chaining.js +++ b/test/chaining.js @@ -12,11 +12,11 @@ $(document).ready(function() { var counts = _(lyrics).chain() .map(function(line) { return line.split(''); }) .flatten() - .reduce({}, function(hash, l) { + .reduce(function(hash, l) { hash[l] = hash[l] || 0; hash[l]++; return hash; - }).value(); + }, {}).value(); ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song'); }); diff --git a/test/collections.js b/test/collections.js index 3759a6495..eb449d690 100644 --- a/test/collections.js +++ b/test/collections.js @@ -53,22 +53,22 @@ $(document).ready(function() { }); test('collections: reduce', function() { - var sum = _.reduce([1, 2, 3], 0, function(sum, num){ return sum + num; }); + var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0); equals(sum, 6, 'can sum up an array'); var context = {multiplier : 3}; - sum = _.reduce([1, 2, 3], 0, function(sum, num){ return sum + num * this.multiplier; }, context); + sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context); equals(sum, 18, 'can reduce with a context object'); - sum = _.inject([1, 2, 3], 0, function(sum, num){ return sum + num; }); + sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0); equals(sum, 6, 'aliased as "inject"'); - sum = _([1, 2, 3]).reduce(0, function(sum, num){ return sum + num; }); + sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0); equals(sum, 6, 'OO-style reduce'); }); test('collections: reduceRight', function() { - var list = _.foldr([1, 2, 3], '', function(memo, num){ return memo + num; }); + var list = _.foldr([1, 2, 3], function(memo, num){ return memo + num; }, ''); equals(list, '321', 'can perform right folds'); }); diff --git a/underscore.js b/underscore.js index b0533cadc..a7274adea 100644 --- a/underscore.js +++ b/underscore.js @@ -92,8 +92,11 @@ // Reduce builds up a single result from a list of values, aka inject, or foldl. // Delegates to JavaScript 1.8's native reduce if available. - _.reduce = function(obj, memo, iterator, context) { - if (nativeReduce && obj.reduce === nativeReduce) return obj.reduce(_.bind(iterator, context), memo); + _.reduce = function(obj, iterator, memo, context) { + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return obj.reduce(iterator, memo); + } each(obj, function(value, index, list) { memo = iterator.call(context, memo, value, index, list); }); @@ -102,10 +105,13 @@ // The right-associative version of reduce, also known as foldr. Uses // Delegates to JavaScript 1.8's native reduceRight if available. - _.reduceRight = function(obj, memo, iterator, context) { - if (nativeReduceRight && obj.reduceRight === nativeReduceRight) return obj.reduceRight(_.bind(iterator, context), memo); + _.reduceRight = function(obj, iterator, memo, context) { + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return obj.reduceRight(iterator, memo); + } var reversed = _.clone(_.toArray(obj)).reverse(); - return _.reduce(reversed, memo, iterator, context); + return _.reduce(reversed, iterator, memo, context); }; // Return the first value which passes a truth test. @@ -277,11 +283,11 @@ // Return a completely flattened version of an array. _.flatten = function(array) { - return _.reduce(array, [], function(memo, value) { + return _.reduce(array, function(memo, value) { if (_.isArray(value)) return memo.concat(_.flatten(value)); memo.push(value); return memo; - }); + }, []); }; // Return a version of the array that does not contain the specified value(s). @@ -293,10 +299,10 @@ // Produce a duplicate-free version of the array. If the array has already // been sorted, you have the option of using a faster algorithm. _.uniq = function(array, isSorted) { - return _.reduce(array, [], function(memo, el, i) { + return _.reduce(array, function(memo, el, i) { if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el); return memo; - }); + }, []); }; // Produce an array that contains every item shared between all the