转换函数(最后有带注释的 convert
):
function convert(data) {
return Object.entries(data)
.map(([type, list]) => {
const big = { type };
const small = list[0]
.map((values, index) => {
if (!values.length) {
return void 0;
}
const [pos, text, correct, type] = values;
return { pos, text, correct, type, index };
})
.filter(it => it);
return { big, small };
})
.filter(it => it.small.length);
}
测试:
const source = {
"data": {
"char": [
[
[],
[29, "新", "心", "char_2"],
[]
]
],
"miss": [
[
[29, "新", "心", "miss_1"],
[],
[29, "新", "心", "miss_2"],
]
],
"order": [
[]
]
}
};
const result = {
event_list: convert(source.data),
};
console.log(JSON.stringify(result, null, 2));
输出:
{
"event_list": [
{
"big": {
"type": "char"
},
"small": [
{
"pos": 29,
"text": "新",
"correct": "心",
"type": "char_2",
"index": 1
}
]
},
{
"big": {
"type": "miss"
},
"small": [
{
"pos": 29,
"text": "新",
"correct": "心",
"type": "miss_1",
"index": 0
},
{
"pos": 29,
"text": "新",
"correct": "心",
"type": "miss_2",
"index": 2
}
]
}
]
}
解释
function convert(data) {
// 转换时,data 对应 event_list。
// data 是一个对象,而 event_list 是一个数组,
// 所以需要先用 Object.entries 或者 Object.keys 把对象变成数组
return Object.entries(data)
// 观察,键(如 char)对应目标的 big,
// 值,对目标的 small
// 下面分别转换,再来组合
.map(([type, list]) => {
// 键这里命名为 type,转换成 big 很容易,用一个对象封装一下就对了
const big = { type };
// 值是一个二维数组,但只用到其第 1 个元素,所以直接用 list[0],
// list[0] 是数组,其中每个元素也是数组,
// 元素中存在空数组,需要过滤(因为目标集中没有空数组),
// 但由于目标集中有 index 数据,所以需要先映射 (map),再过滤,否则 index 会变
const small = list[0]
.map((values, index) => {
// values 就是 list[0] 中的每一个元素,
// 如果是空数组,返回 undefined,方便后面过滤
if (!values.length) {
return void 0;
}
// 否则根据目标对象的键和数组位置的对应关系,
// 将 values 转换成对象
const [pos, text, correct, type] = values;
return { pos, text, correct, type, index };
})
// 这里过滤掉前面 map 中特意生成的 undefined
.filter(it => it);
// 组合 big 和 small,就是目标对象
return { big, small };
})
// 如果 small 是空数组,过滤掉(例中 order 的情况)
.filter(it => it.small.length);
}