"Flatten"对象数组?



使用纯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这样的字段之外的所有属性。

现代语法可以让你这样做:

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);

浏览器支持是有限的,所以如果需要,请使用transpiler。


这对.reduce()回调的第二个参数中的对象文字使用了新的rest语法。所以基本上,studies数组被放入它自己的变量中,rest将是一个具有所有剩余属性的对象。

然后,我们对数组文字使用扩展语法,将当前累加器数组的成员以及studies中新对象的映射放入回调结果中。

.map()回调中,我们使用object literalspread语法.reduce()回调中的rest对象的属性以及当前"研究"对象的属性分配给一个新的object literals,并返回该对象。

如果没有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}这样的方括号表达式求值,这将清除它,但现在他们没有

最新更新