使用纯JS或Lodash“压扁”JSON对象数组的最佳方法是什么?
例如我有一个数组
[
{
"name": "Mat",
"age": "18",
"studies": [
{
"subject": "English",
"mark": 5
},
{
"subject": "Maths",
"mark": 4
}
],
},
{
"name": "Alice",
"age": 20,
"city": "New York"
}
]
我希望得到像
这样的东西[
{
"name": "Mat",
"age": "18",
"subject": "English",
"mark": 5
},
{
"name": "Mat",
"age": "18",
"subject": "Maths",
"mark": 4
},
{
"name": "Alice",
"age": 20,
"city": "New York"
}
]
编辑:工作代码类似于
rows.forEach(row => {
let newRow = {}
_.forOwn(row, (value, key) => {
value.forEach(item => {
_.forOwn(item, (value, key) => {
newRow[key] = value
})
})
} else {
newRow[key] = value
}
})
})
它不提供像name
这样的第一级属性,现在它已经足够我的理由了,但现在我需要获取除了studies
之类的字段之外的所有属性。
答案 0 :(得分:2)
现代语法可以让你这样做:
var d = [{"name":"Mat","age":"18","studies":[{"subject":"English","mark":5},{"subject":"Maths","mark":4}]},{"name":"Alice","age":20,"city":"New York"}];
var r = d.reduce((a, {studies, ...rest}) =>
[...a, ...(studies || [{}]).map(s => ({...s, ...rest}))]
, []);
console.log(r);

浏览器支持有限,因此如果需要,请使用转发器。
这在.reduce()
回调的第二个参数中使用新的 rest语法作为对象文字。所以基本上,studies
数组被放入它自己的变量中,而rest
将是一个包含所有剩余属性的对象。
然后我们使用扩展语法来表示数组文字,以便将当前累加器数组的成员以及新对象从studies
映射到回调结果中。
在.map()
回调中,我们使用对象文字传播语法从rest
回调中分配.reduce()
对象的属性,以及当前"研究的特性"对象返回一个新的对象文字。
如果没有studies
,我们将空数组替换为空对象,以便它至少获得rest
属性。
如果要变平的键是动态的,你仍然可以这样做,虽然它要长一点。
var d = [{"name":"Mat","age":"18","studies":[{"subject":"English","mark":5},{"subject":"Maths","mark":4}]},{"name":"Alice","age":20,"city":"New York"}];
function flatten(key, data) {
return data.reduce((a, user) => {
const arr = user[key];
delete user[key];
return [...a, ...(arr || [{}]).map(s => ({...s, ...user}))]
}, []);
}
console.log(flatten("studies", d));

如果解构语法允许像{[key], ...user}
这样的方括号表达式评估,那么它会清理它,但是现在它们不会