从键数组和值数组创建一个对象

106

我有两个数组:newParamArrparamVal

newParamArr 数组中的示例值为:["Name", "Age", "Email"]

paramVal 数组中的示例值为:["Jon", 15, "jon@gmail.com"]

我需要创建一个 JavaScript 对象,将数组中的所有项放入同一个对象中。例如 {[newParamArr [0]]:paramVal [0],[newParamArr [1]]:paramVal [1],...}

在这种情况下,结果应该是 { Name: "Jon", "Age": 15, "Email": "jon@gmail.com" }

这两个数组的长度始终相同,但数组的长度可以增加或减少。这意味着 newParamArr.length === paramVal.length 总是成立。

以下任何帖子都不能回答我的问题:

Javascript Recursion for creating a JSON object

Recursively looping through an object to build a property list


请添加一些 newParamArrparamVal 的数据以及所需的结果。 - Nina Scholz
@NinaScholz 示例已添加 - user6535476
1
这与递归有什么关系? - Felix Kling
@FelixKling 刚刚在做一些研究,然后那个术语出现了,让人觉得没有它很难做到。 - user6535476
重复的从两个数组创建对象 - Felix Kling
显示剩余4条评论
9个回答

193

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

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

或者,您还可以使用Object.assign

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

或者对象展开语法(ES2018):

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

或者 Object.fromEntries(ES2019):

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

如果您正在使用lodash,那么有一个_.zipObject,专门用于处理这种情况。


是的,那就是我想要的结果,让我来测试一下! - user6535476
2
可能是有史以来最简短和简单的答案。运行得非常好! - abhishake
3
“ES2018”的示例只是一个花哨的反模式!在每次N次迭代中内部传播对象太昂贵了——因为只需要简单的赋值就可以完成。 - Roko C. Buljan
1
目前,如果您对两个键不唯一的数组使用此方法(即“foo”在键数组中出现多次),则最终会得到一个减少的对象,其中每个键的值仅为最后匹配值。较早的值将丢失。(这非常令人沮丧!)如何修改此方法,以便将值累积到每个键的所有匹配值的数组中,或者可能是所有匹配值的总和? 我想使用 lodash 的 _.groupBy 来创建这些组,但它似乎只能按值而不是按键进行分组。 - Francis Barton
使用forEach似乎也非常快速:https://jsperf.app/sezabi。 - undefined

10

使用 ECMAScript 2015:

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

(编辑) 之前误解了OP想要一个数组:

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

这将返回一个由单键对象组成的数组;它不会将所有内容合并为一个对象。你应该使用 reduce - Jacob
1
@craigmichaelmartin 尽管您的原始回答未满足OP的要求,但确实正是我正在寻找的。即:动态地将两个数组中的值映射并组合成单独的对象。谢谢! - SeaWarrior404

8

我在几个地方都需要这个功能,所以我写了这个函数...

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} 

5

我知道这个问题已经一年了,但是这里有一个一行解决方案:

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

1
它只有一行,但是创建了一个不必要的中间数组。 - bernie

4
下面的方法对我有效。
//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);

我现在也做了同样的事情,看着这个,这是最好的方法来准确地查看循环元素正在发生什么。 - MFarooqi

2
您可以使用Object.assign.apply()将一个包含{key:value}对的数组合并到您想要创建的对象中:
Object.assign.apply({}, keys.map( (v, i) => ( {[v]: values[i]} ) ) )

一个可运行的代码片段:

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}

请查看文档获取更多信息。


1

Object.fromEntries 接受一个键值对数组,并将它们压缩成一个对象返回,你可以按以下方式使用它:

    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}
    

0

这个对我有效。

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


0
使用循环:
var result = {};
for (var i = 0; i < newParamArr.length; i++) {
  result[newParamArr[i]] = paramArr[i];
}

也测试一下这个。 - user6535476

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接