如何将键值元组数组转换为对象

81

我有一个数组:

[ [ 'cardType', 'iDEBIT' ],
  [ 'txnAmount', '17.64' ],
  [ 'txnId', '20181' ],
  [ 'txnType', 'Purchase' ],
  [ 'txnDate', '2015/08/13 21:50:04' ],
  [ 'respCode', '0' ],
  [ 'isoCode', '0' ],
  [ 'authCode', '' ],
  [ 'acquirerInvoice', '0' ],
  [ 'message', '' ],
  [ 'isComplete', 'true' ],
  [ 'isTimeout', 'false' ] ]

但是我无法通过数组的键访问数据,例如arr['txnId']不能返回20181。我该如何将上述元组数组转换为对象,以便我可以轻松地通过键访问数据。


我们之前讨论过如何将数组转换为对象,你可以参考此内容并根据你的需求得出最佳解决方案。 https://dev59.com/l2855IYBdhLWcg3wp2N0 - ANR Upgraded Version
3
数组也是对象。;-) - RobG
14个回答

101

根据baao notes,自2019年起,您可以在所有现代浏览器上使用Object.fromEntries(arr)docs)来精确执行此操作:

var arr = [['cardType', 'iDEBIT'],
  ['txnAmount', '17.64'],
  ['txnId', '20181']];

console.log(Object.fromEntries(arr));

如果不可用,我的先前解决方案是将其映射到一个键值对象数组,并通过spreading将对象组合成Object.assign
Object.assign(...arr.map(([key, val]) => ({[key]: val})))

2
计算属性名也可以在{[d[0]]: d[1]}中使用 :) - Chalk
4
Object.assign.apply(null, arr.map(([key, val]) => { return { [key]: val } })) 这样写可以更容易阅读和理解(如果分成多行)。 - royhowie
什么是三个点(...)? - ctrl-alt-delor
1
一个类似的一行代码(使用reduce)具有更好的可链接性优势:arr.reduce((obj, d) => Object.assign(obj, {[d[0]]: d[1]}), {}) - Toph
1
Object.assign(...array.map( ([key, val]) => ({ [key]: val }) )) — 这是@Toph的答案和@royhowie的评论的结合。 - ooo
显示剩余2条评论

62

2020年6月更新

ECMAScript 2021引入了Object.fromEntries,该方法正好实现了此要求:

const array =    [ [ 'cardType', 'iDEBIT' ],
      [ 'txnAmount', '17.64' ],
      [ 'txnId', '20181' ],
      [ 'txnType', 'Purchase' ],
      [ 'txnDate', '2015/08/13 21:50:04' ],
      [ 'respCode', '0' ],
      [ 'isoCode', '0' ],
      [ 'authCode', '' ],
      [ 'acquirerInvoice', '0' ],
      [ 'message', '' ],
      [ 'isComplete', 'true' ],
      [ 'isTimeout', 'false' ] ];
      
const obj = Object.fromEntries(array);
console.log(obj);

这将完成它:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries

const array =    [ [ 'cardType', 'iDEBIT' ],
      [ 'txnAmount', '17.64' ],
      [ 'txnId', '20181' ],
      [ 'txnType', 'Purchase' ],
      [ 'txnDate', '2015/08/13 21:50:04' ],
      [ 'respCode', '0' ],
      [ 'isoCode', '0' ],
      [ 'authCode', '' ],
      [ 'acquirerInvoice', '0' ],
      [ 'message', '' ],
      [ 'isComplete', 'true' ],
      [ 'isTimeout', 'false' ] ];
    
var obj = {};
array.forEach(function(data){
    obj[data[0]] = data[1]
});
console.log(obj);



4
下面的新的Map(array)解决方案似乎更加简单明了。 - Alexander K
甚至可以使用“reduce”方法来得出答案。 - Ben jamin

45

更加惯用的方法是使用 Array.prototype.reduce:

var arr = [
  [ 'cardType', 'iDEBIT' ],
  [ 'txnAmount', '17.64' ],
  [ 'txnId', '20181' ],
  [ 'txnType', 'Purchase' ],
  [ 'txnDate', '2015/08/13 21:50:04' ],
  [ 'respCode', '0' ],
  [ 'isoCode', '0' ],
  [ 'authCode', '' ],
  [ 'acquirerInvoice', '0' ],
  [ 'message', '' ],
  [ 'isComplete', 'true' ],
  [ 'isTimeout', 'false' ]
];

var obj = arr.reduce(function (o, currentArray) {
  var key = currentArray[0], value = currentArray[1]
  o[key] = value
  return o
}, {})

console.log(obj)
document.write(JSON.stringify(obj).split(',').join(',<br>'))

使用ES6(剩余参数)语法可以使这个过程更具视觉吸引力:

let obj = arr.reduce((o, [ key, value ]) => {
    o[key] = value
    return o
}, {})

4
避免参数重新赋值的更清晰的方法是:使用reduce方法将数组转化为对象。示例代码如下:const obj = arr.reduce((obj, [key, value]) => { return { ...obj, [key]: value }; }, {}); - huygn
1
甚至可以避免使用return语句: const obj = arr.reduce(obj, [key, value] => ({ ...obj, [key]: value }), {}) - Nils Magne Lunde

34

使用 Map

new Map(array);

Map对象保存键值对并记住键的原始插入顺序。任何值(包括对象和基本值)都可以用作键或值。

这是因为你的变量array的类型是Array<[key,value]>Map构造函数可用由内部数组组成的数组初始化,其中内部数组的第一个元素是键,第二个元素是值。

const array = [
  ['cardType', 'iDEBIT'],
  ['txnAmount', '17.64'],
  ['txnId', '20181'],
  ['txnType', 'Purchase'],
  ['txnDate', '2015/08/13 21:50:04'],
  ['respCode', '0'],
  ['isoCode', '0'],
  ['authCode', ''],
  ['acquirerInvoice', '0'],
  ['message', ''],
  ['isComplete', 'true'],
  ['isTimeout', 'false']
];

const obj = new Map(array);

console.log(obj.get('txnDate'));


6
不要这样做,太简单了^^ - kashiraja
1
@Rick,我有点困惑。我刚在控制台中尝试了这个:array = [['a', 1],['b','two'],['c', [3,3,3]]] 然后 obj = new Map(array);。然而,obj.aobj['a'] 都是未定义的。那么这怎么能实现目标呢? - abalter
3
@RickViscomi -- 好的,我不知道Map对象。然而,我认为大多数人想要得到的是普通的JS对象。 - abalter
4
不确定大多数人寻找什么,但原问题是寻找给定属性txnDate的值'2015/08/13 21:50:04',我认为这是最语义化的方法。 - Rick Viscomi
1
@PA. typeof new Map() // "object" :)`@PA. typeof new Map() // "object" :)` - Rick Viscomi
显示剩余4条评论

15
arr.reduce((o, [key, value]) => ({...o, [key]: value}), {})

8
使用 Object.fromEntries,您可以将Array转换为Object:

var entries = [
  ['cardType', 'iDEBIT'],
  ['txnAmount', '17.64'],
  ['txnId', '20181'],
  ['txnType', 'Purchase'],
  ['txnDate', '2015/08/13 21:50:04'],
  ['respCode', '0'],
  ['isoCode', '0'],
  ['authCode', ''],
  ['acquirerInvoice', '0'],
  ['message', ''],
  ['isComplete', 'true'],
  ['isTimeout', 'false']
];
var obj = Object.fromEntries(entries);
console.log(obj);


1
这很酷,只是要注意,截至撰写本文时,它的状态为:草案。评论是:在ECMAScript 2019中进行了初始定义。 - Joseph Connolly

3

使用.reduce()的ES5版本

const object = array.reduce(function(accumulatingObject, [key, value]) {
  accumulatingObject[key] = value;
  return accumulatingObject;
}, {});

我该怎么使用这个?抱歉,我是JavaScript新手,不确定如何调用它? - Paul Kenjora
@PaulKenjora 在代码中 const object = array.reduce ... array 是原始数组的变量名,而 object 则是你要赋新值的变量名。它已经被调用,并将值分配给一个新变量 object - sudo soul

3
使用以下方式来轻松地将数组转换为对象。
var obj = {};
array.forEach(function(e){
   obj[e[0]] = e[1]
})

这将使用每个元素的第一个元素作为键,第二个元素作为值。

2

使用Airbnb代码风格的ES6简洁写法

例子:

const obj = arr.reduce((prevObj, [key, value]) => ({ ...prevObj, [key]: value }), {});

2

这个的新JS API是Object.fromEntries(元组数组),它可以与原始数组和/或Maps一起使用。

最初的回答

1
请提供一个代码示例,将您的建议与发布问题的用户的代码结合起来,使您的答案更有用。 - Keith Dawson

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