如何将JS对象转换为数组

43

我需要转换一个哈希映射。

{ 
    "fruit" : ["mango","orange"],
    "veg"   : ["carrot"]
} 
[ 
  { "type" : "fruit" , "name" : ["mango","orange"] } ,
  { "type" : "veg" ,   "name" : ["carrot"] } 
]

我该如何做到这一点??


我想知道如何双向实现。 - Sam
请记得始终提供一些代码缩进,这会使问题更易于阅读。 - Fabrizio Calderan
感谢您的编辑...下次会记住的。 - Sam
2
请注意,JavaScript 没有“哈希映射”,只有“对象”。 - maerics
8个回答

44

您可以像这样完成它(在可工作的片段中):

var input = { 
    "fruit" : ["mango","orange"],
    "veg"   : ["carrot"]
} 

var output = [], item;

for (var type in input) {
    item = {};
    item.type = type;
    item.name = input[type];
    output.push(item);
}

// display result
document.write(JSON.stringify(output));

或者,如果你或其他人已经使用可枚举属性扩展了 Object 原型(我个人认为这是一种不好的做法),那么你可以使用以下代码来保护自己:

var input = { 
    "fruit" : ["mango","orange"],
    "veg"   : ["carrot"]
} 

var output = [], item;

for (var type in input) {
    if (input.hasOwnProperty(type)) {
        item = {};
        item.type = type;
        item.name = input[type];
        output.push(item);
    }
}

// display result
document.write(JSON.stringify(output));


而且,利用一些更为现代的功能:

var input = { 
    "fruit" : ["mango","orange"],
    "veg"   : ["carrot"]
};

var output = Object.keys(input).map(function(key) {
   return {type: key, name: input[key]};
});

// display the result
document.write(JSON.stringify(output));


2
我建议在 for...in 循环内部检查 hasOwnProperty - gen_Eric
1
@Rocket 我不建议在 for...in 循环内部检查 hasOwnProperty。 - Anurag Uniyal
1
@Rocket:如果他们没有扩展Object.prototype,为什么会这样做呢? - user1106925
6
在我的回答中,我向OP提供了两个选项(带有或不带有hasOwnProperty())。我个人不允许在我的页面中扩展Object,因此我不必添加额外的代码来防止它。如果我处于可能出现这种情况的环境中,我会编写代码以防止它发生。 - jfriend00
添加了一个更现代的版本,使用 Object.keys().map(),并将所有示例转换为可工作的代码片段。 - jfriend00
显示剩余4条评论

28
在支持ES5的浏览器中 - 或者您已为其添加了shim
var stuff = { 
    "fruit" : ["mango","orange"],
    "veg"   : ["carrot"]
}

var array = Object.keys(stuff).map(function(key) {
    return {"type" : key, "name" : stuff[key] }
})

请参见:Object.keysArray的map

或者,以老式的方式:

var stuff = { 
    "fruit" : ["mango","orange"],
    "veg"   : ["carrot"]
}

var array = []

for (var key in stuff) {
    if (stuff.hasOwnProperty(key)) {
        array.push({"type" : key, "name" : stuff[key] })
    }
}

请注意,在这两种情况下,数组的值是共享的,因为在JS中,对象是按引用传递的。例如,stuff ["fruit"]array [0] .name指向数组["mango", "orange"]的相同引用。这意味着,如果你改变其中一个,另一个也会被改变:
stuff["fruit"].push("apple");
alert(array[0].name); // "mango", "orange", "apple"

为了避免这种情况,您可以使用slice来获得数组的一级深拷贝。因此,在上面的代码中,可以使用以下方式代替:
"name" : stuff[key]

你将拥有:

"name" : stuff[key].slice(0)

希望能有所帮助。

11

对于那些使用ES6 maps的人...

假设您已经...

const m = new Map()
m.set("fruit",["mango","orange"]);
m.set("veg",["carrot"]);

您可以使用...

const arr = Array.from(map, ([key, val]) => {
  return {type: key, name: val};
});

请注意,Array.from 不仅接受数组对象,还接受可迭代对象。


7
我可以提供一个“一行解决方案”:
var b = Object.keys(a).map(e => { return { type:e, name:a[e] } });

为您提供经济的文字服务。问题要求将对象转换为数组,因此我不会重复上面的答案,对吧?


1

虽然这不完全是你所寻找的答案,但对于一般目的可能会有用。

var hash2Array = function(hash, valueOnly) {
  return Object.keys(hash).map(function(k) {
    if (valueOnly) {
      return hash[k];
    } else {
      var obj={};
      obj[k] = hash[k];
      return obj;
    }
  });
};

//output
hash2Array({a:1, b:2});     // [{a:1}, {b:2}]
hash2Array({a:1, b:2},true) // [1,2]

1

看起来很简单,你的地图的键是类型,值是名称,所以只需遍历地图并将对象插入列表中,例如:

var d = { "fruit" : ["mango","orange"],"veg" :["carrot"]} 
var l = []
for(var type in d){
    l.push({'type':type, 'name': d[type]})
}
console.log(l)

输出:

[{"type":"fruit","name":["mango","orange"]},{"type":"veg","name":["carrot"]}]

1
这不是关于“过早优化”的问题:这只是良好的实践和预防头痛的方法。 - Fabrizio Calderan
1
@Rocket:这没有太多意义。为什么一个人要破坏他们正在访问的页面呢?如果他们想这样做,那没问题,但这最多只是一个学术观点。 - user1106925
1
@amnotiam,这不是破坏的问题:如果另一个js库向Object.prototype添加内容会怎么样?你怎么能确定这永远不会发生呢? - Fabrizio Calderan
1
@F.Calderan:对你正在使用的代码一无所知并不是一个很好的论点。程序员在使用库之前应该知道它的作用。如果它扩展了 Object.prototype,那么你应该停止使用它。而 Rocket 的例子是一种破坏行为。 - user1106925
2
@Rocket 如果有人在我不知道的情况下修改对象,那么他就可以更改例如Array.prototype.join = function(){alert("hacked!')} ,那么现在你会说我应该使用任何数组方法吗? - Anurag Uniyal
显示剩余30条评论

0

如果使用underscore.js的话:

var original = { 
   "fruit" : ["mango","orange"],
   "veg"   : ["carrot"]
}
var converted = _.map(original, function(name, type){
   return {
      type: type, 
      name: name
   };
});

-1

无需循环

var a = { 
   "fruit" : ["mango","orange"],    
   "veg"   : ["carrot"]


};  

var b = [  
    { "type" : "fruit" , "pop" : function(){this.name = a[this.type]; delete this.pop; return this} }.pop() ,          
    { "type" : "veg" ,   "pop" : function(){this.name = a[this.type]; delete this.pop; return this} }.pop()   
]

这太奇怪了。至少重用函数 ;) - drzaus

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