bra*_*ipt 21 javascript arrays json javascript-objects
我有一些像这样的结构化JSON数据.让我们假设这是可以互换的,通过JSON.parse():
[
{
"title": "pineapple",
"uid": "ab982d34c98f"
},
{
"title": "carrots",
"uid": "6f12e6ba45ec"
}
]
Run Code Online (Sandbox Code Playgroud)
我需要它看起来像这样,重新映射title到name,并uid以id与结果:
[
{
"name": "pineapple",
"id": "ab982d34c98f"
},
{
"name": "carrots",
"id": "6f12e6ba45ec"
}
]
Run Code Online (Sandbox Code Playgroud)
最明显的做法是这样的:
str = '[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots", "uid": "6f12e6ba45ec"}]';
var arr = JSON.parse(str);
for (var i = 0; i<arr.length; i++) {
arr[i].name = arr[i].title;
arr[i].id = arr[i].uid;
delete arr[i].title;
delete arr[i].uid;
}
Run Code Online (Sandbox Code Playgroud)
str = '[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots", "uid": "6f12e6ba45ec"}]';
var arr = JSON.parse(str);
for (var i = 0; i<arr.length; i++) {
arr[i].name = arr[i].title;
arr[i].id = arr[i].uid;
delete arr[i].title;
delete arr[i].uid;
}
$('body').append("<pre>"+JSON.stringify(arr, undefined, 4)+"</pre>");Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>Run Code Online (Sandbox Code Playgroud)
...或者使用更复杂的东西(虽然不是像更有效)这个.
这一切都很好,花花公子,但如果阵列中有200,000个对象怎么办?这是很多处理开销.
是否有更有效的方法来重新映射密钥名称?可能没有遍历整个对象数组?如果您的方法更有效,请提供证明/参考.
Fel*_*ing 25
正如我在评论中已经提到的,如果您可以对对象的值做出某些假设,则可以使用正则表达式来替换键,例如:
str = str.replace(/"title":/g, '"name":');
Run Code Online (Sandbox Code Playgroud)
它不像"干净",但可能会更快地完成工作.
如果你必须解析JSON,更结构化的方法是将reviver函数传递给JSON.parse你,你可能可以避免对数组进行额外的传递.这可能取决于引擎如何实现JSON.parse(也许它们首先解析整个字符串,然后使用reviver函数进行第二次传递,在这种情况下,您将无法获得任何优势).
var arr = JSON.parse(str, function(prop, value) {
switch(prop) {
case "title":
this.name = value;
return;
case "uid":
this.id = value;
return;
default:
return value;
}
});
Run Code Online (Sandbox Code Playgroud)
基准测试,使用下面的Node.js脚本测试3次:
1389822740739: Beginning regex rename test
1389822740761: Regex rename complete
// 22ms, 22ms, 21ms
1389822740762: Beginning parse and remap in for loop test
1389822740831: For loop remap complete
// 69ms, 68ms, 68ms
1389822740831: Beginning reviver function test
1389822740893: Reviver function complete
// 62ms, 61ms, 60ms
Run Code Online (Sandbox Code Playgroud)
似乎正则表达式(在这种情况下)是最有效的,但在尝试使用正则表达式解析JSON时要小心.
测试脚本,加载OP的样本JSON的100,230行:
fs = require('fs');
fs.readFile('test.json', 'utf8', function (err, data) {
if (err) {
return console.log(err);
}
console.log(new Date().getTime() + ": Beginning regex rename test");
var str = data.replace(/"title":/g, '"name":');
str = str.replace(/"uid":/g, '"id":');
JSON.parse(str);
console.log(new Date().getTime() + ": Regex rename complete");
console.log(new Date().getTime() + ": Beginning parse and remap in for loop test");
var arr = JSON.parse(data);
for (var i = 0; i < arr.length; i++) {
arr[i].name = arr[i].title;
arr[i].id = arr[i].uid;
delete arr[i].title;
delete arr[i].uid;
}
console.log(new Date().getTime() + ": For loop remap complete");
console.log(new Date().getTime() + ": Beginning reviver function test");
var arr = JSON.parse(data, function (prop, value) {
switch (prop) {
case "title":
this.name = value;
return;
case "uid":
this.id = value;
return;
default:
return value;
}
});
console.log(new Date().getTime() + ": Reviver function complete");
});
Run Code Online (Sandbox Code Playgroud)
bra*_*ipt 12
很久以前问过这个问题,从那以后,我已经习惯了使用Array.prototype.map()来完成工作,更多的是为了稳定性和代码的清洁度而不是性能.虽然它当然不是最高效的,但它看起来很棒:
var repl = orig.map(function(obj) {
return {
name: obj.title,
id: obj.uid
}
})
Run Code Online (Sandbox Code Playgroud)
如果您需要更灵活(和ES6兼容的功能),请尝试:
let replaceKeyInObjectArray = (a, r) => a.map(o =>
Object.keys(o).map((key) => ({ [r[key] || key] : o[key] })
).reduce((a, b) => Object.assign({}, a, b)))
Run Code Online (Sandbox Code Playgroud)
例如
const arr = [{ abc: 1, def: 40, xyz: 50 }, { abc: 1, def: 40, xyz: 50 }, { abc: 1, def: 40, xyz: 50 }]
const replaceMap = { "abc": "yyj" }
replaceKeyInObjectArray(arr, replaceMap)
/*
[
{
"yyj": 1,
"def": 40,
"xyz": 50
},
{
"yyj": 1,
"def": 40,
"xyz": 50
},
{
"yyj": 1,
"def": 40,
"xyz": 50
}
]
*/
Run Code Online (Sandbox Code Playgroud)
小智 8
这是对OP的建议的另一种看法,map()用于清晰度(而不是性能).
var newItems = items.map(item => ({
name: item.title,
id: item.uid
}));
Run Code Online (Sandbox Code Playgroud)
这使用ES6箭头函数和当只有一个parm传递给函数时可能的快捷语法,并且函数体中只有一个语句.
根据您使用各种语言的lambda表达式的历史记录,此表单可能会或可能不会与您产生共鸣.
使用箭头函数快捷方式语法返回对象文字时要小心.不要忘记对象字面周围的额外parens!