diff --git a/lodash.js b/lodash.js index 234a98621..bedd53c5f 100644 --- a/lodash.js +++ b/lodash.js @@ -1508,7 +1508,8 @@ * `thru`, `toArray`, `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, * `transform`, `unary`, `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, * `uniqWith`, `unset`, `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, - * `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, and `zipWith` + * `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, `zipObject`, + * and `zipWith` * * The wrapper methods that are **not** chainable by default are: * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, @@ -5611,40 +5612,27 @@ } /** - * The inverse of `_.toPairs`; this method returns an object composed from arrays - * of property names and values. Provide either a single two dimensional array, - * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names - * and one of corresponding values. + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. * * @static * @memberOf _ * @category Array - * @param {Array} props The property names. - * @param {Array} [values=[]] The property values. + * @param {Array} pairs The key-value pairs. * @returns {Object} Returns the new object. * @example * * _.fromPairs([['fred', 30], ['barney', 40]]); * // => { 'fred': 30, 'barney': 40 } - * - * _.fromPairs(['fred', 'barney'], [30, 40]); - * // => { 'fred': 30, 'barney': 40 } */ - function fromPairs(props, values) { + function fromPairs(pairs) { var index = -1, - length = props ? props.length : 0, + length = pairs ? pairs.length : 0, result = {}; - if (length && !values && !isArray(props[0])) { - values = []; - } while (++index < length) { - var key = props[index]; - if (values) { - baseSet(result, key, values[index]); - } else if (key) { - baseSet(result, key[0], key[1]); - } + var pair = pairs[index]; + baseSet(result, pair[0], pair[1]); } return result; } @@ -6770,6 +6758,33 @@ */ var zip = rest(unzip); + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property names and one of corresponding values. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} [props=[]] The property names. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['fred', 'barney'], [30, 40]); + * // => { 'fred': 30, 'barney': 40 } + */ + function zipObject(props, values) { + var index = -1, + length = props ? props.length : 0, + valsLength = values ? values.length : 0, + result = {}; + + while (++index < length) { + baseSet(result, props[index], index < valsLength ? values[index] : undefined); + } + return result; + } + /** * This method is like `_.zip` except that it accepts `iteratee` to specify * how grouped values should be combined. The iteratee is invoked with four @@ -13775,6 +13790,7 @@ lodash.xorBy = xorBy; lodash.xorWith = xorWith; lodash.zip = zip; + lodash.zipObject = zipObject; lodash.zipWith = zipWith; // Add aliases. diff --git a/test/test.js b/test/test.js index e130d1ca3..723e10db5 100644 --- a/test/test.js +++ b/test/test.js @@ -5989,26 +5989,6 @@ var object = { 'barney': 36, 'fred': 40 }, array = [['barney', 36], ['fred', 40]]; - QUnit.test('should skip falsey elements in a given two dimensional array', function(assert) { - assert.expect(1); - - var actual = _.fromPairs(array.concat(falsey)); - assert.deepEqual(actual, object); - }); - - QUnit.test('should zip together key/value arrays into an object', function(assert) { - assert.expect(1); - - var actual = _.fromPairs(['barney', 'fred'], [36, 40]); - assert.deepEqual(actual, object); - }); - - QUnit.test('should ignore extra `values`', function(assert) { - assert.expect(1); - - assert.deepEqual(_.fromPairs(['a'], [1, 2]), { 'a': 1 }); - }); - QUnit.test('should accept a two dimensional array', function(assert) { assert.expect(1); @@ -6016,13 +5996,6 @@ assert.deepEqual(actual, object); }); - QUnit.test('should not assume `keys` is two dimensional if `values` is not provided', function(assert) { - assert.expect(1); - - var actual = _.fromPairs(['barney', 'fred']); - assert.deepEqual(actual, { 'barney': undefined, 'fred': undefined }); - }); - QUnit.test('should accept a falsey `array` argument', function(assert) { assert.expect(1); @@ -6040,7 +6013,7 @@ QUnit.test('should support deep paths', function(assert) { assert.expect(1); - var actual = _.fromPairs(['a.b.c'], [1]); + var actual = _.fromPairs([['a.b.c', 1]]); assert.deepEqual(actual, { 'a': { 'b': { 'c': 1 } } }); }); @@ -21437,6 +21410,50 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.zipObject'); + + (function() { + var object = { 'barney': 36, 'fred': 40 }, + array = [['barney', 36], ['fred', 40]]; + + QUnit.test('should zip together key/value arrays into an object', function(assert) { + assert.expect(1); + + var actual = _.zipObject(['barney', 'fred'], [36, 40]); + assert.deepEqual(actual, object); + }); + + QUnit.test('should ignore extra `values`', function(assert) { + assert.expect(1); + + assert.deepEqual(_.zipObject(['a'], [1, 2]), { 'a': 1 }); + }); + + QUnit.test('should support deep paths', function(assert) { + assert.expect(1); + + var actual = _.zipObject(['a.b.c'], [1]); + assert.deepEqual(actual, { 'a': { 'b': { 'c': 1 } } }); + }); + + QUnit.test('should work in a lazy chain sequence', function(assert) { + assert.expect(1); + + if (!isNpm) { + var values = lodashStable.range(LARGE_ARRAY_SIZE), + props = lodashStable.map(values, function(value) { return 'key' + value; }), + actual = _(props).zipObject(values).map(square).filter(isEven).take().value(); + + assert.deepEqual(actual, _.take(_.filter(_.map(_.zipObject(props, values), square), isEven))); + } + else { + skipTest(assert); + } + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.zipWith'); (function() { @@ -22562,7 +22579,7 @@ var acceptFalsey = lodashStable.difference(allMethods, rejectFalsey); QUnit.test('should accept falsey arguments', function(assert) { - assert.expect(280); + assert.expect(281); var emptyArrays = lodashStable.map(falsey, lodashStable.constant([])); diff --git a/test/underscore.html b/test/underscore.html index c3074012b..e870a12f9 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -73,6 +73,10 @@ 'should treat non-number `fromIndex` values as `array.length`', '[0,-1,-1]' ], + 'object': [ + 'an array of pairs zipped together into an object', + 'an object converted to pairs and back to an object' + ], 'rest': [ 'working rest(0)', 'rest can take an index', @@ -343,13 +347,12 @@ 'mapObject': 'mapValues', 'matcher': 'matches', 'methods': 'functions', - 'object': 'fromPairs', + 'object': 'zipObject', 'pairs': 'toPairs', 'pluck': 'map', 'restParam': 'restArgs', 'select': 'filter', - 'where': 'filter', - 'zipObject': 'fromPairs' + 'where': 'filter' }; var keyMap = {