如何将 JavaScript 中的 Object {} 转换为 key-value 对的 Array []?

462

我想将一个像这样的对象转换:

{"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}

成为这样的键值对数组:

[[1,5],[2,7],[3,0],[4,0]...].

如何将JavaScript中的Object转换为键-值对数组?

23个回答

701
你可以使用 Object.keys()map() 来实现这个功能。

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result = Object.keys(obj).map((key) => [key, obj[key]]);

console.log(result);


16
你是否在使用数字作为键?如果不是,则在尝试将键转换为数字时,它将失败并返回NaN。 如果你想使用字符串作为键,请将返回值从[Number(key), obj[key]]更改为[key, obj[key]],或者按照@Pila在他们的答案中建议的那样使用Object.entries - scottbot95
对我来说,它运行得很好。我需要转换以下对象:let res ={"5":"ManuscriptRequestId","4":"PublishRequestId","9":"AuthorIdentificationId","1":"VisitRequestId","6":"InformationRequestId","3":"RareDocumnetsRequestId","2":"RarePhotoRequestId","7":"BookPurchaseRequestId","8":"StatmentRequestId"}const dataArray = Object.entries(res).map(([key, value]) => ({ key, value })); - Rohit Gaidhane

324

最好的方法是这样做:

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result = Object.entries(obj);

console.log(result);

如本示例所示,调用entries将返回[key, value]对,正如调用者要求的那样。

或者,您可以调用Object.values(obj),它将仅返回值。


1
FYI:Object.entries将返回[key,value],但键将是字符串,值将不同。 - SHAHBAZ
13
使用 Object.fromEntries() 可以将 [key, value] 键值对转换回对象。 - etoxin
Object.values()没有正确的“keys”...假设对象的键都是数字。 - Max Waterman

81

Object.entries() 返回一个数组,其中的元素是与 object 直接关联的可枚举属性 [key, value] 对应的数组。属性的顺序与手动遍历对象属性值时给出的顺序相同。

- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Description

Object.entries 函数返回的几乎就是你所要求的输出,唯一不同的是键是字符串而不是数字。

const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

console.log(Object.entries(obj));

如果你需要键是数字,你可以使用回调函数将结果映射到一个新数组中,并将每个键替换为从中强制转换的数字。

const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

const toNumericPairs = input => {
    const entries = Object.entries(input);
    return entries.map(entry => Object.assign(entry, { 0: +entry[0] }));
}

console.log(toNumericPairs(obj));

我在上面的示例中使用了箭头函数和Object.assign来进行映射回调,以便通过利用Object.assign返回被分配对象的事实,并且单指令箭头函数的返回值是指令的结果,将其保留在一条指令中。
这相当于:
entry => {
    entry[0] = +entry[0];
    return entry;
}

如评论中@TravisClarke所提到的,map函数可以缩短为:

entry => [ +entry[0], entry[1] ]

然而,这会为每个键值对创建一个新的数组,而不是直接在原有数组中进行修改,因此将创建的键值对数组数量翻倍。虽然原始entries数组仍然可访问,但它及其条目将不会被垃圾回收。
现在,即使使用我们的就地方法仍然使用两个保存键值对的数组(输入和输出数组),但总数组数只增加了一个。输入和输出数组实际上并没有填充数组,而是引用数组,并且这些引用在内存中占用的空间非常小。
就地修改每个键值对导致内存增长微不足道,但需要输入更多字符。
为每个键值对创建一个新数组会导致所需内存翻倍,但需要输入较少的字符。
您可以进一步消除增长,通过就地修改entries数组而不是映射到新数组:

const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

const toNumericPairs = input => {
  const entries = Object.entries(obj);
  entries.forEach(entry => entry[0] = +entry[0]);
  return entries;
}

console.log(toNumericPairs(obj));


1
我喜欢函数式编程方法。作为一种更简短的替代方案:Object.entries(obj).map(e => [+e[0], e[1]]); - Travis Clarke

33

回顾一些关于 ES6 标准的答案。

从对象开始:

let const={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
  • 只盲目地获取数组中的值,不关心键:

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.values(obj));
//[9,8,7,6,5,4,3,2,1,0,5]

  • 获取数组中的键值对:

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj));
//[["1",9],["2",8],["3",7],["4",6],["5",5],["6",4],["7",3],["8",2],["9",1],["10",0],["12",5]]

  • 与之前相同,但每个键都带有数字键:

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj).map(([k,v])=>[+k,v]));
//[[1,9],[2,8],[3,7],[4,6],[5,5],[6,4],[7,3],[8,2],[9,1],[10,0],[12,5]]

  • 使用对象属性作为新数组的键(可能会创建稀疏数组):

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj).reduce((ini,[k,v])=>(ini[k]=v,ini),[]));
//[undefined,9,8,7,6,5,4,3,2,1,0,undefined,5]

这种最后一种方法,还可以根据键的值重新组织数组顺序。有时这可能是期望的行为(有时不是)。但现在的优点是,值被索引到了正确的数组槽位上,对它进行搜索是必要且微不足道的。

  • 使用 Map 替代 Array

最后(不是原始问题的一部分,但为了完整起见),如果您需要使用键或值轻松搜索,但不想使用稀疏数组,也不想有重复项和无需转换为数字键而不会进行重新排序(甚至可以访问非常复杂的键),那么数组(或对象)并不是您所需的。我将推荐使用 Map

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

let r=new Map(Object.entries(obj));
r.get("4"); //6
r.has(8); //true

2
第四个要点及其后面的内容与问题完全无关,而您的回答只是总结了前三个答案。这个答案没有为讨论带来任何新的东西,或者是完全无关的。 - user4639281
是的,正如第一行所述,这是答案的摘要,然后将它们更新为使用现代的ES6技术而不是完整的函数。第四个答案在您将JSON数组从支持关联数组(例如PHP)的语言移动时非常有用。 - CarlosH.
这里提供的所有方法已经在前三个答案中以它们的普通形式提供了,它们不是函数,所以我不知道你在说什么。至于第四个,正如我所说,它与所问的问题完全无关。它可能与其他问题相关,但不是这个问题。无论是使用PHP、JavaScript还是Haskell创建,JSON都是JSON。 - user4639281

30
在ECMAScript 6中,
var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

var res = Object.entries(obj);

console.log(res);

var obj = {
  "1": 5,
  "2": 7,
  "3": 0,
  "4": 0,
  "5": 0,
  "6": 0,
  "7": 0,
  "8": 0,
  "9": 0,
  "10": 0,
  "11": 0,
  "12": 0
};
var res = Object.entries(obj);
console.log(res);


23

如果 Object.entries 对你不起作用,另一个解决方案是使用以下方法。

const obj = {
      '1': 29,
      '2': 42
    };
const arr = Array.from(Object.keys(obj), k=>[`${k}`, obj[k]]);
console.log(arr);


1
这对我很有帮助。遇到一个问题,导入JSON时添加的索引使得使用Angulars ngFor循环变得不可能。这个方法去除了索引同时保留了结构。 - RAC
@RAC +1,因为使用“indexes”而不是“indices”。消失吧,古老的(即武断和毫无意义的)英语传统! - Venryx

10

使用 Object.entries 方法以 键 & 值 格式获取对象的每个元素,然后像这样通过map 进行遍历:

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}

var res = Object.entries(obj).map(([k, v]) => ([Number(k), v]));

console.log(res);

但是,如果您确信键将以渐进顺序出现,您可以使用Object.valuesArray#map执行类似于以下内容的操作:

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; 

                        // idx is the index, you can use any logic to increment it (starts from 0)
let result = Object.values(obj).map((e, idx) => ([++idx, e]));

console.log(result);


10
使用 Object.keysArray#map 方法。

var obj = {
  "1": 5,
  "2": 7,
  "3": 0,
  "4": 0,
  "5": 0,
  "6": 0,
  "7": 0,
  "8": 0,
  "9": 0,
  "10": 0,
  "11": 0,
  "12": 0
};
// get all object property names
var res = Object.keys(obj)
  // iterate over them and generate the array
  .map(function(k) {
    // generate the array element 
    return [+k, obj[k]];
  });

console.log(res);


9

您可以使用Object.values([]),如果您还没有,则可能需要使用此 polyfill:

const objectToValuesPolyfill = (object) => {
  return Object.keys(object).map(key => object[key]);
};
Object.values = Object.values || objectToValuesPolyfill;

然后你只需要做这个步骤:

https://dev59.com/WVkS5IYBdhLWcg3wECuU#54822153

var object = {1: 'hello', 2: 'world'};
var array = Object.values(object);

请记住,在js中,数组只能使用数值键,因此如果您在对象中使用了其他内容,则这些内容将变为“0、1、2...x”。

例如,如果您有一个唯一的键,那么删除重复项可能会很有用。

var obj = {};
object[uniqueKey] = '...';

8
使用Lodash,除了上面提供的答案之外,你还可以在输出数组中包含键。

不包含对象键名的输出数组

循环:

const array = _.values(obj);

如果 obj 是以下内容:
{ “art”: { id: 1,  title: “aaaa” }, “fiction”: { id: 22,  title: “7777”} }

那么数组将会是:

[ { id: 1, title: “aaaa” }, { id: 22, title: “7777” } ]

使用输出数组中的对象键

如果你改为写成('genre'是你选择的字符串):

const array= _.map(obj, (val, id) => {
    return { ...val, genre: key };
  });

您将获得:

[ 
  { id: 1, title: “aaaa” , genre: “art”}, 
  { id: 22, title: “7777”, genre: “fiction” }
]

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