113

I have two arrays: newParamArr and paramVal.

Example values in the newParamArr array: [ "Name", "Age", "Email" ].

Example values in the paramVal array: [ "Jon", 15, "[email protected]" ].

I need to create a JavaScript object that places all of the items in the array in the same object. For example { [newParamArr[0]]: paramVal[0], [newParamArr[1]]: paramVal[1], ... }.

In this case, the result should be { Name: "Jon", "Age": 15, "Email": "[email protected]" }.

The lengths of the two arrays are always the same, but the length of arrays can increase or decrease. That means newParamArr.length === paramVal.length will always hold.

None of the below posts could help to answer my question:

Javascript Recursion for creating a JSON object

Recursively looping through an object to build a property list

9
  • please add some data of newParamArr and paramVal and the wanted result. Commented Aug 24, 2016 at 16:00
  • @NinaScholz Examples added Commented Aug 24, 2016 at 16:04
  • 1
    What does this have to do with recursion? Commented Aug 24, 2016 at 16:07
  • @FelixKling Was just doing some research and that term popped up, made it seem like it was hard to do without it. Commented Aug 24, 2016 at 16:09
  • is the value of newParamArr[i]an array with the content ["Name", "Age", "Email"]or is the array newParamArr = ["Name", "Age", "Email"]? Commented Aug 24, 2016 at 16:12

10 Answers 10

197

var keys = ['foo', 'bar', 'baz'];
var values = [11, 22, 33]

var result = {};
keys.forEach((key, i) => result[key] = values[i]);
console.log(result);

Alternatively, you can use Object.assign

result = Object.assign(...keys.map((k, i) => ({[k]: values[i]})))

or the object spread syntax (ES2018):

result = keys.reduce((o, k, i) => ({...o, [k]: values[i]}), {})

or Object.fromEntries (ES2019):

Object.fromEntries(keys.map((_, i) => [keys[i], values[i]]))

In case you're using lodash, there's _.zipObject exactly for this type of thing.

Sign up to request clarification or add additional context in comments.

5 Comments

Yes that is the result I wanted, let me test it!
Probably the short and simple answer ever. Working like a charm!
The "ES2018" example is just a fancy antipattern! Spreading Objects internally, on every N iteration is way too expensive - when just a simple assignment is all it takes.
Currently if you use this method on two arrays where keys are not unique (ie 'foo' appears multiple time in the keys array), you end up with a reduced object where the value for each key is just the last matched value. And earlier values are lost. (It's very frustrating!) How can this approach be amended so that the values are accumulated into an array of all matching values for each key, or perhaps instead a sum of all matching values? I wanted to use _.groupBy from lodash to create these groups but that only seems to group by value, not by key.
Using forEach seems to be quite speedy as well: jsperf.app/sezabi.
10

Using ECMAScript2015:

const obj = newParamArr.reduce((obj, value, index) => {
    obj[value] = paramArr[index];
    return obj;
}, {});

(EDIT) Previously misunderstood the OP to want an array:

const arr = newParamArr.map((value, index) => ({[value]: paramArr[index]}))

2 Comments

This will return an array of single-key objects; it will not combine everything into one object. You'd want reduce instead.
@craigmichaelmartin While your original answer did not satisfy OP's requirements, it however was exactly what I was looking for. ie. Mapping values from two arrays and combining them into individual objects dynamically. Thankyou!
8

I needed this in a few places so I made this function...

function zip(arr1,arr2,out={}){
    arr1.map( (val,idx)=>{ out[val] = arr2[idx]; } );
    return out;
}


console.log( zip( ["a","b","c"], [1,2,3] ) );

> {'a': 1, 'b': 2, 'c': 3} 

Comments

5

I know that the question is already a year old, but here is a one-line solution:

Object.assign( ...newParamArr.map( (v, i) => ( {[v]: paramVal[i]} ) ) );

2 Comments

It's 1 line, but it creates an unnecessary intermediate array
@bernie and lots of unnecessary objects
4

The following worked for me.

//test arrays
var newParamArr = [1, 2, 3, 4, 5];
var paramVal = ["one", "two", "three", "four", "five"];

//create an empty object to ensure it's the right type.
var obj = {};

//loop through the arrays using the first one's length since they're the same length
for(var i = 0; i < newParamArr.length; i++)
{
    //set the keys and values
    //avoid dot notation for the key in this case
    //use square brackets to set the key to the value of the array element
    obj[newParamArr[i]] = paramVal[i];
}

console.log(obj);

1 Comment

i did the same now looking at this, This is best way to see exactly what is happening with loop elements.
2

You can use Object.assign.apply() to merge an array of {key:value} pairs into the object you want to create:

Object.assign.apply({}, keys.map( (v, i) => ( {[v]: values[i]} ) ) )

A runnable snippet:

var keys = ['foo', 'bar', 'baz'];
var values = [11, 22, 33]

var result =  Object.assign.apply({}, keys.map( (v, i) => ( {[v]: values[i]} ) ) );
console.log(result); //returns {"foo": 11, "bar": 22, "baz": 33}

See the documentation for more

Comments

1

This one works for me.

    var keys = ['foo', 'bar', 'baz'];
    var values = [11, 22, 33]
    var result = {};
    keys.forEach(function(key, i){result[key] = values[i]});
    console.log(result);

Comments

1

Object.fromEntries takes an array of key, value tuples and return the zipped result as object, you can then use it as follow:

    const keys = ["a","b","c"];
    const values = [1,2,3];
    Object.fromEntries(keys.map((key, index)=> [key, values[index]])); // {a: 1, b: 2, c: 3}
    

Comments

0

Use a loop:

var result = {};
for (var i = 0; i < newParamArr.length; i++) {
  result[newParamArr[i]] = paramArr[i];
}

Comments

0

A function using Array.reduce

const keys = ['foo', 'bar', 'baz'];
const values = [11, 22, 33];

console.log(combine2Object({keys, values}));
console.log(combine2Object());

function combine2Object( {keys = [`empty`], values = [true]} = {} ) {
  return keys.reduce( (acc, v, i) => ({...acc, [v]: values[i]}), {});
}

But, but, but, my teacher says I can't use loops!

Ok.

const keys = ['foo', 'bar', 'baz'];
const values = [11, 22, 33];
const obj = {};
obj[keys[0]] = values[0];
obj[keys[1]] = values[1];
obj[keys[2]] = values[2];

console.log(obj);

// or if you want to impress your teacher
// even more
const wowzer = {
  [keys[0]]: values[0],
  [keys[1]]: values[1],
  [keys[2]]: values[2],
};

console.log(`Wowzer! `, wowzer);

Now ask your teacher what to do when you can't use loops and the length of keys-/values arrays is not known up front.

Comments