62

I have:

var keys = [ "height", "width" ];
var values = [ "12px", "24px" ];

And I'd like to convert it into this object:

{ height: "12px", width: "24px" }

In Python, there's the simple idiom dict(zip(keys,values)). Is there something similar in jQuery or plain JavaScript, or do I have to do this the long way?

Penny Liu
18k5 gold badges89 silver badges109 bronze badges
asked Jul 13, 2009 at 6:18
1

14 Answers 14

45

The simplest ES6 one-liner solution using Object fromEntries:

const keys = ['height', 'width'];
const values = ['12px', '24px'];
const merged = Object.fromEntries(keys.map((key, i) => [key, values[i]]));
console.log(merged);
answered Jun 22, 2018 at 10:26
Sign up to request clarification or add additional context in comments.

Comments

32

Simple JS function would be:

function toObject(names, values) {
 var result = {};
 for (var i = 0; i < names.length; i++)
 result[names[i]] = values[i];
 return result;
}

Of course you could also actually implement functions like zip, etc as JS supports higher order types which make these functional-language-isms easy :D

answered Jul 13, 2009 at 6:22

2 Comments

If names have same key, this function will fail.
@user1927627 No, it won't. It will just use the last occurrence, exactly as one would expect.
27

use lodash.

_.zipObject

Example

_.zipObject(['a', 'b'], [1, 2]);
// ➜ { 'a': 1, 'b': 2 }
answered Aug 17, 2016 at 9:18

2 Comments

This should be the accepted answer. Rolling it yourself (like in all other answers) is a waste of time. The original name of this function from Underscore (which you'll also find in older versions of Lodash) is _.object.
Include the whole lib just for this? Rolling it myself does not pull in tons of unused code.
19

As an alternate solution, not already mentioned I think :

const keys = ["height", "width"];
const values = ["12px", "24px"];
const result = {};
keys.forEach((key, idx) => result[key] = values[idx]);
console.log(result);

isherwood
61.4k16 gold badges122 silver badges173 bronze badges
answered Oct 10, 2016 at 9:54

Comments

13
+250

You can combine two arrays with map method, then convert it with Object.fromEntries.

var keys = ["height", "width"];
var values = ["12px", "24px"];
var array = keys.map((el, i) => {
 return [keys[i], values[i]];
});
// → [["height", "12px"], ["width", "24px"]]
var output = Object.fromEntries(array);
// → {height: "12px", width: "24px"}
console.log(output);

answered Jun 21, 2019 at 8:00

Comments

7

A functional approach with immutability in mind:

const zipObj = xs => ys => xs.reduce( (obj, x, i) => ({ ...obj, [x]: ys[i] }), {})
const arr1 = ['a', 'b', 'c', 'd']
const arr2 = ['e', 'f', 'g', 'h']
const obj = zipObj (arr1) (arr2) 
console.log (obj)

answered Jul 12, 2018 at 13:10

2 Comments

Can you point me to some docs on the detailed diference of zipObj(arr1, arr2) and zipObj(arr1)(arr2)?
@JefersonEuclides Hey, the second is known as currying and partial application.
4

You could use a reduce() function to map the key-value pairs to an object.

/**
 * Apply to an existing or new object, parallel arrays of key-value pairs.
 *
 * @param {string[]} keys - List of keys corresponding to their accociated values.
 * @param {object[]} vals - List of values corresponding to their accociated keys.
 * @param {object} [ref={}] - Optional reference to an existing object to apply to.
 *
 * @returns {object} - The modified or new object with the new key-value pairs applied.
 */
function toObject(keys, vals, ref) {
 return keys.length === vals.length ? keys.reduce(function(obj, key, index) {
 obj[key] = vals[index];
 return obj;
 }, ref || {}) : null;
}
var keys = [ "height" , "width" ];
var values = [ "12px" , "24px" ];
document.body.innerHTML = '<pre>' + JSON.stringify(toObject(keys, values), null, 2) + '</pre>';

answered Mar 8, 2016 at 20:23

Comments

4

Now we have Object.fromEntries we can do something like that:

const keys = [ "height", "width" ];
const values = [ "12px", "24px" ];
const myObject = Object.fromEntries(
 values.map((value, index) => [keys[index], value])
);
console.log(myObject);

answered Aug 26, 2021 at 13:55

Comments

3

Here's an example with all consts (non-modifying) and no libraries.

const keys = ["Adam", "Betty", "Charles"];
const values = [50, 1, 90];
const obj = keys.reduce((acc, key, i) => {
 acc[key] = values[i];
 return acc;
}, {});
console.log(obj);

Alternatively, if you'd consider libraries you could use lodash zipobject which does just what you asked.

answered Nov 29, 2020 at 3:03

Comments

2

You could transpose the arrays and get the object with the entries.

const
 transpose = (r, a) => a.map((v, i) => [...(r[i] || []), v]),
 keys = [ "height", "width" ],
 values = [ "12px", "24px" ],
 result = Object.fromEntries([keys, values].reduce(transpose, []));
console.log(result);

answered May 14, 2020 at 18:03

Comments

1
function combineObject( keys, values)
{
 var obj = {};
 if ( keys.length != values.length)
 return null;
 for (var index in keys)
 obj[keys[index]] = values[index];
 return obj;
};
var your_obj = combine( your_keys, your_values);
answered Jul 13, 2009 at 6:22

3 Comments

heh, i saw you fixed it so removed the comment, which you then responded to -- hurrah for async conversation :D You should also avoid new Object as Object may be changed, but {} is spec'd as using the original Object constructor.
The function is still incorrect. combineObject(["height", "width"], ["12px", "24px"]).height incorrectly returns "24px".
Thanks I've fixed it according to your comment, but I'm not sure that can be an issue, since once somebody changes the Object it's on purpose so maybe it better to be implied on all objects you will have.
1

Here's one which will transform nested arrays into an array of multiple key-value objects.

var keys = [
 ['#000000', '#FFFFFF'],
 ['#FFFF00', '#00FF00', '#00FFFF', '#0000FF'],
];
var values = [
 ['Black', 'White'],
 ['Yellow', 'Green', 'Cyan', 'Blue'],
];
const zipObj = xs => ys => xs.reduce( (obj, x, i) => ({ ...obj, [x]: ys[i] }), {})
var array = keys.map((el, i) => zipObj (keys[i]) (values[i]));
console.log(array);

Output is

[
 {
 "#000000": "Black",
 "#FFFFFF": "White"
 },
 {
 "#FFFF00": "Yellow",
 "#00FF00": "Green",
 "#00FFFF": "Cyan",
 "#0000FF": "Blue"
 }
]
answered Dec 12, 2020 at 6:12

Comments

0

Providing a solution with a for...of loop.

var keys = ["height", "width"];
var values = ["12px", "24px"];
const result = {};
for (let [index, key] of keys.entries())
 result[key] = values[index];
console.log(result);
You can also use a library like ramda which has zipObj function. Example:

const keys = ["height", "width"];
const values = ["12px", "24px"];
const result = R.zipObj(keys, values);
console.log(result);
answered Nov 27, 2022 at 15:58

Comments

-1

In the jQuery-Utils project, the ArrayUtils module has a zip function implemented.

//...
zip: function(object, object2, iterator) {
 var output = [];
 var iterator = iterator || dummy;
 $.each(object, function(idx, i){
 if (object2[idx]) { output.push([i, object2[idx]]); }
 });
 return output;
}
//...
answered Jul 13, 2009 at 6:23

1 Comment

Hmm, but then what do you do with the array of tuples?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.