Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
331 views
in Technique[技术] by (71.8m points)

困扰很久的,js数组转换问题

输入数组格式如下

{
    "data": {
        "char": [
            [
                [],
                [29, "新", "心", "char_2"],
                []
            ]
        ],
        "miss": [
            [
                [29, "新", "心", "miss_1"],
                [],
                [29, "新", "心", "miss_2"],
            ]
        ],
        "order": [
            []
        ]
    }
}

如何转换为下面这个形式

{
    "event_list": [
        {
            "big": {
                "type": "char"
            },
            "small": [
                {
                    "type": "char_2",
                    "correct": "心",
                    "text": "新",
                    "pos": 10,
                    "index": 1
                }
            ]
        },
        {
            "big": {
                "type": "miss"
            },
            "small": [
                {
                    "type": "miss_1",
                    "correct": "心",
                    "text": "新",
                    "pos": 20,
                    "index": 0
                },
                {
                    "type": "miss_2",
                    "correct": "心",
                    "text": "新",
                    "pos": 10,
                    "index": 2
                }
            ]
        }
    ]
}

请教各位大佬如何转换?感谢


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

转换函数(最后有带注释的 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);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...