将嵌套的 JSON 对象展平并排序到 javascript 中的数组中
Flatten and sort a nested JSON object into an array in javascript
我有一个像这样的对象:
{
'2021': {
'08': {
'26': [{'name': 'Bob', age: 34}, {'name': 'Alice', age: 33}],
'27': [{'name': 'Jane', age: 21}]
},
'09': {
'03': [{'name': 'John', age: 47}, {'name': 'Sue', age: 36}]
}
},
'2022': {
'04': {
'05': [{'name': 'David', age: 26}]
}
}
}
我想将此对象展平为 <year, month, day, name, age>
个按日期降序排列的对象数组,因此所需的输出为:
[
{'year': '2022', 'month': '04', 'day': '05', 'name': 'David', age: 26},
{'year': '2021', 'month': '09', 'day': '03', 'name': 'John', age: 47},
{'year': '2021', 'month': '09', 'day': '03', 'name': 'Sue', age: 36},
{'year': '2021', 'month': '08', 'day': '27', 'name': 'Jane', age: 21},
{'year': '2021', 'month': '08', 'day': '26', 'name': 'Bob', age: 34},
{'year': '2021', 'month': '08', 'day': '26', 'name': 'Alice', age: 33},
]
更新:
我按照Nina的逻辑,也拆成两部分,先压平成单深度数组,再排序。展平部分我有一个“更丑陋”的嵌套 for 循环,它也可以工作并使用完全相同的排序代码:
let output = []
for (const year in data) {
for (const month in data[year]) {
for (const day in data[year][month]) {
for (const person of data[year][month][day]) {
const merged = Object.assign({
'year': year,
'month': month,
'day': day,
}, person)
output.push(merged)
}
}
}
}
这不是那么灵活,我不确定如何判断性能差异,但我会接受 Nina 的有效答案。
您可以将任务分成两部分,
- 通过递归从数据中获取平面数组,
- 按需要的键降序排序。
const
flat = (object, [key, ...keys], values = {}) => Object
.entries(object)
.flatMap(([k, v]) => {
const right = { ...values, [key]: k };
return Array.isArray(v)
? v.map(o => ({ ...right, ...o }))
: flat(v, keys, right);
}),
keys = ['year', 'month', 'day'],
data = { 2021: { '08': { 26: [{ name: 'Bob', age: 34 }, { name: 'Alice', age: 33 }], 27: [{ name: 'Jane', age: 21 }] }, '09': { '03': [{ name: 'John', age: 47 }, { name: 'Sue', age: 36 }] } }, 2022: { '04': { '05': [{ name: 'David', age: 26 }] } } },
result = flat(data, keys)
.sort((a, b) => {
let r;
keys.some(k => r = b[k] - a[k]);
return r;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我有一个像这样的对象:
{
'2021': {
'08': {
'26': [{'name': 'Bob', age: 34}, {'name': 'Alice', age: 33}],
'27': [{'name': 'Jane', age: 21}]
},
'09': {
'03': [{'name': 'John', age: 47}, {'name': 'Sue', age: 36}]
}
},
'2022': {
'04': {
'05': [{'name': 'David', age: 26}]
}
}
}
我想将此对象展平为 <year, month, day, name, age>
个按日期降序排列的对象数组,因此所需的输出为:
[
{'year': '2022', 'month': '04', 'day': '05', 'name': 'David', age: 26},
{'year': '2021', 'month': '09', 'day': '03', 'name': 'John', age: 47},
{'year': '2021', 'month': '09', 'day': '03', 'name': 'Sue', age: 36},
{'year': '2021', 'month': '08', 'day': '27', 'name': 'Jane', age: 21},
{'year': '2021', 'month': '08', 'day': '26', 'name': 'Bob', age: 34},
{'year': '2021', 'month': '08', 'day': '26', 'name': 'Alice', age: 33},
]
更新:
我按照Nina的逻辑,也拆成两部分,先压平成单深度数组,再排序。展平部分我有一个“更丑陋”的嵌套 for 循环,它也可以工作并使用完全相同的排序代码:
let output = []
for (const year in data) {
for (const month in data[year]) {
for (const day in data[year][month]) {
for (const person of data[year][month][day]) {
const merged = Object.assign({
'year': year,
'month': month,
'day': day,
}, person)
output.push(merged)
}
}
}
}
这不是那么灵活,我不确定如何判断性能差异,但我会接受 Nina 的有效答案。
您可以将任务分成两部分,
- 通过递归从数据中获取平面数组,
- 按需要的键降序排序。
const
flat = (object, [key, ...keys], values = {}) => Object
.entries(object)
.flatMap(([k, v]) => {
const right = { ...values, [key]: k };
return Array.isArray(v)
? v.map(o => ({ ...right, ...o }))
: flat(v, keys, right);
}),
keys = ['year', 'month', 'day'],
data = { 2021: { '08': { 26: [{ name: 'Bob', age: 34 }, { name: 'Alice', age: 33 }], 27: [{ name: 'Jane', age: 21 }] }, '09': { '03': [{ name: 'John', age: 47 }, { name: 'Sue', age: 36 }] } }, 2022: { '04': { '05': [{ name: 'David', age: 26 }] } } },
result = flat(data, keys)
.sort((a, b) => {
let r;
keys.some(k => r = b[k] - a[k]);
return r;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }