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?

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);
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

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 }

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);

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);

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)

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>';

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);

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.

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);

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);

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"
  }
]

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);

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;
}
//...

1 Comment

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

Your Answer

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.