如何从键值对数组中创建对象?

时间:2013-11-18 23:13:52

标签: javascript

在Python中,可以将dict 1 构造函数传递给一系列键值对:

>>> dict([['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']])
{'age': 42, 'name': 'Bob', 'breakfast': 'eggs'}

除了为此目的定义自己的函数之外,我想不出用JavaScript做任何事情的方法:

function pairs_to_object(pairs) {
    var ret = {};
    pairs.forEach(function (p) { ret[p[0]] = p[1]; });
    return ret;
}

但我是一个JS noob ......这种对对象转换有内置的东西吗?

1 出于这个问题的目的,我将Python dicts视为Python对象的JS对象,当然,相似之处仅限于它们都是键值集合。

6 个答案:

答案 0 :(得分:39)

您可以使用缩小功能

x = [[1,2],[3,4],[5,6]];
o = x.reduce(function(prev,curr){prev[curr[0]]=curr[1];return prev;},{})

o现在相当于{1:2, 3:4, 5:6}

如果输入数组稀疏,您需要在作业中添加if(curr!=undefined)测试,但请确保仍然返回“prev”。

如果你的元组比简单的[key,value]更复杂,你可以简单地改变“prev”的分配方式。例如:prev["key-"+curr[0].toString()]=curr[1]*2;

答案 1 :(得分:38)

Object.fromEntries完成这项工作。在撰写本文时,它是第3阶段的ES提案,可在FireFox 63和Chrome 73中使用。

在该功能广泛使用之前,您可以使用以下ES6代码自行定义:

Object.fromEntries = arr => Object.assign({}, ...Array.from(arr, ([k, v]) => ({[k]: v}) ));

一个好处是这个方法与Object.entries(ES2017)相反,所以现在你可以在对象和数组表示之间来回走动:

Object.fromEntries = arr => 
    Object.assign({}, ...Array.from(arr, ([k, v]) => ({[k]: v}) ));

// Demo:
const arr = [['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']];
const obj = Object.fromEntries(arr);
console.log(obj);
// ... and back:
const arr2 = Object.entries(obj);
console.log(arr2); // copy of the original array (omitting duplicate keys)
.as-console-wrapper { max-height: 100% !important; top: 0; }

ES6地图

对于键/值对,可以使用普通对象的替代方法:Map

它的构造函数接受数组对齐格式:

// Demo:
const arr = [['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']];

const mp = new Map(arr);

// Get one particular value:
console.log(mp.get('age'));
// Get all the keys:
console.log(...mp.keys());
// Get all the values:
console.log(...mp.values());
// Get all the key/value pairs:
console.log(...mp.entries());

如果你真的需要一个普通的对象,那么这没用,但Map可能会提供一个可行的选择。

答案 2 :(得分:12)

在撰写本文时(2013年),JavaScript对象/字典/关联数组本身没有这样的构造函数。

正如您自己所说,您当然可以使用reduce函数的功能方法构建自己的函数,如其他答案中所述。当然,经典或更新的forEach循环也可以使用。但是没有任何内置的东西。


修改:现在是2019年,现在我们有了Object.fromEntries,它可以满足您的需求。

答案 3 :(得分:8)

Lodash的fromPairs功能会执行此操作:

const _ = require('lodash')
const kvPairs = [['a', 1], ['b', 2]]
_.fromPairs(kvPairs)
// => { a: 1, b: 2 }

答案 4 :(得分:1)

Javascript没有以您所描述的方式将数组转换为对象的本机函数。但是,这是因为没有必要。您已经在问题中包含了一个示例解决方案,您可以自己定义该函数,但这实际上并不是必需的。只要您可以确定输入数组是正确的,您甚至可以使用简单的for循环进行转换,如下所示:

var input = [['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']];
var output = {};
for(i in input) output[input[i][0]] = input[i][1];

这是可以想象的最基本的代码。

当然,(正如mamapitufo指出的那样)实际上使用for..in迭代数组通常是一个坏主意,因为这也会将非索引作为i的值返回。不过,重点是这种操作过于简单,而且很少需要,以证明拥有原生功能。

python dict是javascript中不需要的结构,因为这两种语言有不同的键入和设计方法,因此对一个语言有用的对另一个语言没用。虽然你可以使用你在python中使用的相同方法和结构,但考虑如何利用javascript不同的做事方式可能是一个更好的主意 - 也许你会发现你不需要一个字典毕竟。

答案 5 :(得分:0)

Object.fromEntries()

Object对象上有一个称为Object.fromEntries(iterable)的方法。来自可迭代对象的迭代器对象必须产生一个包含2个元素的数组。第一个(索引为0)数组元素将为对象键,第二个为值。

MDN非常准确地描述了这一点:

  

Object.fromEntries()方法采用键值对列表,   返回一个新对象,其属性由这些条目提供。的   迭代参数应为实现   @@iterator方法,返回一个迭代器对象,该对象生成一个   两元素数组状对象,其第一个元素是一个值   将用作属性键,其第二个元素是值   与该属性键关联。


使用方法:

使用Object.fromEntries()方法甚至不需要知道可迭代对象的详细信息。您可以始终在以下对象上使用该方法:

  • 2维数组,其中内部/嵌套数组具有2个元素
  • 地图

这里是一个例子:

// map example:
const map = new Map([ ['hi', 'there'], ['foo', 2] ]);
const objFromMap = Object.fromEntries(map);
console.log(objFromMap); // { hi: "there", foo: 2 }

// array example:
const array = [ ['0', '00'], ['1', '11'], ['2', '22'] ];
const objFromArray = Object.fromEntries(array);
console.log(objFromArray); // { 0: "00", 1: "11", 2: "22" }

注意,与浏览器兼容!

在撰写本文时(2019年12月),该方法相对较新,并非所有浏览器都实现。为了使用此方法并确保您的JS代码将在所有浏览器中运行,您可能必须将代码转换为较早版本的JS。