From b1d52ccd82caa374094b9c872883cdb622537a46 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 29 Aug 2015 11:42:37 -0700 Subject: [PATCH] Rename `_.indexBy` to `_.keyBy` to avoid confusion with `_.sortedIndexBy` forms. --- lodash.js | 68 ++++++++++---------- perf/perf.js | 36 ----------- test/backbone.html | 1 + test/test.js | 144 +++++++++++++++++++++---------------------- test/underscore.html | 3 + 5 files changed, 110 insertions(+), 142 deletions(-) diff --git a/lodash.js b/lodash.js index dc9e33dfd..147373083 100644 --- a/lodash.js +++ b/lodash.js @@ -805,8 +805,8 @@ * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, * `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, `flatten`, * `flattenDeep`, `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, - * `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, - * `initial`, `intersection`, `invert`, `invoke`, `iteratee`, `keys`, `keysIn`, + * `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `initial`, + * `intersection`, `invert`, `invoke`, `iteratee`, `keyBy`, `keys`, `keysIn`, * `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, `memoize`, * `merge`, `mergeWith` `method`, `methodOf`, `mixin`, `modArgs`, `negate`, * `omit`, `omitBy`, `once`, `pairs`, `partial`, `partialRight`, `partition`, @@ -6197,37 +6197,6 @@ : (!!length && getIndexOf(collection, target, fromIndex) > -1); } - /** - * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iteratee`. The corresponding value - * of each key is the last element responsible for generating the key. The - * iteratee is invoked with one argument: (value). - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns the composed aggregate object. - * @example - * - * var keyData = [ - * { 'dir': 'left', 'code': 97 }, - * { 'dir': 'right', 'code': 100 } - * ]; - * - * _.indexBy(keyData, 'dir'); - * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } - * - * _.indexBy(keyData, function(o) { - * return String.fromCharCode(o.code); - * }); - * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } - */ - var indexBy = createAggregator(function(result, value, key) { - result[key] = value; - }); - /** * Invokes the method at `path` of each element in `collection`, returning * an array of the results of each invoked method. Any additional arguments @@ -6263,6 +6232,37 @@ return result; }); + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var keyData = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(keyData, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(keyData, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + /** * Creates an array of values by running each element in `collection` through * `iteratee`. The iteratee is invoked with three arguments: @@ -11455,12 +11455,12 @@ lodash.flowRight = flowRight; lodash.functions = functions; lodash.groupBy = groupBy; - lodash.indexBy = indexBy; lodash.initial = initial; lodash.intersection = intersection; lodash.invert = invert; lodash.invoke = invoke; lodash.iteratee = iteratee; + lodash.keyBy = keyBy; lodash.keys = keys; lodash.keysIn = keysIn; lodash.map = map; diff --git a/perf/perf.js b/perf/perf.js index 27b291dba..097ab75ce 100644 --- a/perf/perf.js +++ b/perf/perf.js @@ -1117,42 +1117,6 @@ /*--------------------------------------------------------------------------*/ - suites.push( - Benchmark.Suite('`_.indexBy` with `callback` iterating an array') - .add(buildName, '\ - lodash.indexBy(numbers, function(num) { return num >> 1; })' - ) - .add(otherName, '\ - _.indexBy(numbers, function(num) { return num >> 1; })' - ) - ); - - suites.push( - Benchmark.Suite('`_.indexBy` with `property` name iterating an array') - .add(buildName, { - 'fn': 'lodash.indexBy(words, "length")', - 'teardown': 'function countBy(){}' - }) - .add(otherName, { - 'fn': '_.indexBy(words, "length")', - 'teardown': 'function countBy(){}' - }) - ); - - suites.push( - Benchmark.Suite('`_.indexBy` with `callback` iterating an object') - .add(buildName, { - 'fn': 'lodash.indexBy(wordToNumber, function(num) { return num >> 1; })', - 'teardown': 'function countBy(){}' - }) - .add(otherName, { - 'fn': '_.indexBy(wordToNumber, function(num) { return num >> 1; })', - 'teardown': 'function countBy(){}' - }) - ); - - /*--------------------------------------------------------------------------*/ - suites.push( Benchmark.Suite('`_.indexOf`') .add(buildName, { diff --git a/test/backbone.html b/test/backbone.html index 2ddbd184e..874e89961 100644 --- a/test/backbone.html +++ b/test/backbone.html @@ -33,6 +33,7 @@ return function(_) { lodash.defaultsDeep(_, { 'templateSettings': lodash.templateSettings }); + lodash.mixin(_ , { 'indexBy': lodash.keyBy }); lodash.mixin(_, lodash.pick(lodash, lodash.difference(lodash.functions(lodash), lodash.functions(_)))); }; }()); diff --git a/test/test.js b/test/test.js index 114e8f1db..ae8d32c48 100644 --- a/test/test.js +++ b/test/test.js @@ -4635,7 +4635,7 @@ 'forOwn', 'forOwnRight', 'groupBy', - 'indexBy', + 'keyBy', 'map', 'mapKeys', 'mapValues', @@ -4665,7 +4665,7 @@ 'forEach', 'forEachRight', 'groupBy', - 'indexBy', + 'keyBy', 'map', 'partition', 'reduce', @@ -5605,74 +5605,6 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.indexBy'); - - (function() { - test('should use `_.identity` when `iteratee` is nullish', 1, function() { - var array = [4, 6, 6], - values = [, null, undefined], - expected = _.map(values, _.constant({ '4': 4, '6': 6 })); - - var actual = _.map(values, function(value, index) { - return index ? _.indexBy(array, value) : _.indexBy(array); - }); - - deepEqual(actual, expected); - }); - - test('should work with a "_.property" style `iteratee`', 1, function() { - var actual = _.indexBy(['one', 'two', 'three'], 'length'); - deepEqual(actual, { '3': 'two', '5': 'three' }); - }); - - test('should only add values to own, not inherited, properties', 2, function() { - var actual = _.indexBy([4.2, 6.1, 6.4], function(num) { - return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; - }); - - deepEqual(actual.constructor, 4.2); - deepEqual(actual.hasOwnProperty, 6.4); - }); - - test('should work with a number for `iteratee`', 2, function() { - var array = [ - [1, 'a'], - [2, 'a'], - [2, 'b'] - ]; - - deepEqual(_.indexBy(array, 0), { '1': [1, 'a'], '2': [2, 'b'] }); - deepEqual(_.indexBy(array, 1), { 'a': [2, 'a'], 'b': [2, 'b'] }); - }); - - test('should work with an object for `collection`', 1, function() { - var actual = _.indexBy({ 'a': 4.2, 'b': 6.1, 'c': 6.4 }, function(num) { - return Math.floor(num); - }); - - deepEqual(actual, { '4': 4.2, '6': 6.4 }); - }); - - test('should work in a lazy chain sequence', 1, function() { - if (!isNpm) { - var array = _.range(LARGE_ARRAY_SIZE).concat( - _.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE), - _.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZE) - ); - - var predicate = function(value) { return value > 2; }, - actual = _(array).indexBy().map(square).filter(predicate).take().value(); - - deepEqual(actual, _.take(_.filter(_.map(_.indexBy(array), square), predicate))); - } - else { - skipTest(); - } - }); - }()); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.indexOf'); (function() { @@ -8466,10 +8398,10 @@ } }); - test('`_.indexBy` should use `_.iteratee` internally', 1, function() { + test('`_.keyBy` should use `_.iteratee` internally', 1, function() { if (!isModularize) { _.iteratee = getLength; - deepEqual(_.indexBy(array), { '3': 'two', '5': 'three' }); + deepEqual(_.keyBy(array), { '3': 'two', '5': 'three' }); _.iteratee = iteratee; } else { @@ -8705,6 +8637,74 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.keyBy'); + + (function() { + test('should use `_.identity` when `iteratee` is nullish', 1, function() { + var array = [4, 6, 6], + values = [, null, undefined], + expected = _.map(values, _.constant({ '4': 4, '6': 6 })); + + var actual = _.map(values, function(value, index) { + return index ? _.keyBy(array, value) : _.keyBy(array); + }); + + deepEqual(actual, expected); + }); + + test('should work with a "_.property" style `iteratee`', 1, function() { + var actual = _.keyBy(['one', 'two', 'three'], 'length'); + deepEqual(actual, { '3': 'two', '5': 'three' }); + }); + + test('should only add values to own, not inherited, properties', 2, function() { + var actual = _.keyBy([4.2, 6.1, 6.4], function(num) { + return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; + }); + + deepEqual(actual.constructor, 4.2); + deepEqual(actual.hasOwnProperty, 6.4); + }); + + test('should work with a number for `iteratee`', 2, function() { + var array = [ + [1, 'a'], + [2, 'a'], + [2, 'b'] + ]; + + deepEqual(_.keyBy(array, 0), { '1': [1, 'a'], '2': [2, 'b'] }); + deepEqual(_.keyBy(array, 1), { 'a': [2, 'a'], 'b': [2, 'b'] }); + }); + + test('should work with an object for `collection`', 1, function() { + var actual = _.keyBy({ 'a': 4.2, 'b': 6.1, 'c': 6.4 }, function(num) { + return Math.floor(num); + }); + + deepEqual(actual, { '4': 4.2, '6': 6.4 }); + }); + + test('should work in a lazy chain sequence', 1, function() { + if (!isNpm) { + var array = _.range(LARGE_ARRAY_SIZE).concat( + _.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE), + _.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZE) + ); + + var predicate = function(value) { return value > 2; }, + actual = _(array).keyBy().map(square).filter(predicate).take().value(); + + deepEqual(actual, _.take(_.filter(_.map(_.keyBy(array), square), predicate))); + } + else { + skipTest(); + } + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('keys methods'); _.each(['keys', 'keysIn'], function(methodName) { diff --git a/test/underscore.html b/test/underscore.html index 943684710..dfe3fc091 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -185,6 +185,8 @@ 'Lookup falsy iterator' ], 'partition': [ + 'can reference the array index', + 'Died on test #8', 'partition takes a context argument', 'function(a){[code]}' ], @@ -317,6 +319,7 @@ 'extendOwn': 'assign', 'findWhere': 'find', 'include': 'includes', + 'indexBy': 'keyBy', 'inject': 'reduce', 'mapObject': 'mapValues', 'matcher': 'matches',