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

IT技术 javascript
2021-01-23 23:55:42

在 Python 中,可以向dict1构造函数传递一系列键值对:

>>> 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 菜鸟......这种对到对象的转换有什么内置的吗?

1就这个问题而言,我将 Python dicts 视为 Python 的 JS 对象的对应物,当然,相似之处仅限于它们都是键值集合这一事实。

6个回答

Object.fromEntries做这项工作。它是通过 EcmaScript2019 添加到语言中的。

如果您不支持该功能,您可以使用以下 ES2015 代码自行定义:

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

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

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 可能会提供一个可行的替代方案。

谢谢@Kostanos。幸运的是,Object.assign我的答案的主要 ( ) 部分可用于生成 JSON ;-) Maps 具有其他特性(例如方便的构造函数、保持插入顺序、允许非字符串作为键、提供size属性,...)在某些用例中很有趣。
2021-03-25 23:55:42
在2018年ES草稿,可以使用对象扩展语法代替Object.assign,如下:<array>.reduce((o, [k, v]) => ({...o, [k]: v}), {})
2021-03-28 23:55:42
不幸的是,如果您想将 Map 序列化为 JSON,则需要额外的工作。否则你的解决方案很酷!+1
2021-04-02 23:55:42
这很棒!谢谢!我对如何/为什么将方括号用于键(即,{[k]: v}感到有些困惑这是一个破坏性的东西吗?我一直在努力弄清楚如何以这种方式使用变量作为键,当我看到这行得通时,我很困惑,但仍然很高兴。
2021-04-02 23:55:42
我会继续自己回答......不,不完全是......任何好奇的人都可以查看这篇文章:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...相关的一点是:“从 ECMAScript 2015 开始,对象初始值设定项语法也支持计算属性名称。这允许您将表达式放在括号 [] 中,该表达式将被计算并用作属性名称。” 我非常喜欢 ES20xx...
2021-04-03 23:55:42

您可以使用减少功能

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;

这是最好的答案,因为它适用于所有浏览器,并且非常紧凑。每个人都应该学习 map、filter 和 reduce。我花了一段时间才找到尾随的 {},它提供了 reduce 的初始值。此外,粗箭头语法会使其更具可读性,但不适用于所有浏览器。
2021-03-19 23:55:42

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

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


编辑:现在是 2019 年,现在我们有了Object.fromEntries,它会给你你需要的东西。

Lodash 的fromPairs函数会这样做:

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

Object.fromEntries()

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

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

Object.fromEntries()方法采用键值对列表并返回一个新对象,其属性由这些条目给出。iterable 参数应该是一个实现 @@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。

像这样,但让我们给它一些时间:)
2021-03-24 23:55:42