首页 > 解决方案 > 将嵌套字典解析为每个级别元素的数组的功能方法

问题描述

我想在 javascript 中以功能样式解决问题。

我的字典看起来像这样:

[{
    "title": "A",
    "isFinal": false,
    "children": [{
            "title": "AA",
            "isFinal": false,
            "children": [{
                    "title": "AAA",
                    "isFinal": true
                },
                {
                    "title": "AAB",
                    "isFinal": true
                }
            ]
        },
        {
            "title": "AB",
            "isFinal": false,
            "children": [{
                    "title": "ABA",
                    "isFinal": true
                },
                {
                    "title": "ABB",
                    "isFinal": true
                }
            ]
        },
        {
            "title": "AC",
            "isFinal": true
        }
    ]
}]

所以这是一棵树,它最多可以有 N (6) 层,并且在任何节点中都可以有更多的叶子。最后一个节点的isFinal字段设置为 true。

我想要以下输出

[["A"], ["AA", "AB", "AC"], ["AAA", "AAB", "ABA", "ABB"]]

这是同一数组中同一级别上每个节点的标题。

我认为它与算法递归下降有某种关系,但我无法弄清楚。

到目前为止,我可以访问第一级:


function parseData (data) {
    const data = new Array();

    return data.filter((dataLevelChild) => (!dataLevelChild.isFinal)).map((dataLevelChild, index) => (
      dataLevelChild.title
    ))
}

但我真的不知道如何传递二级元素并将所有内容存储在一个数组中。

另一种方法是使用 forEach

function parseData (data) {
    const parsedData = new Array();

    const parse = (e) => {
      parsedData.push({
          id: e.title,
      });

      e.children && e.children.forEach(parse);
  }

  return data.forEach(parse);

这是不正确的,但至少我可以访问每个元素。它是否具有功能性?它看起来不像我,因为通常你不会像这样在功能风格中使用 .push

标签: javascriptrecursionfunctional-programming

解决方案


您可以收集所有嵌套级别并将下一级的标题分配给收集数组。

const
    getTitles = data => data.reduce((r, { title, children }) => {
        (r[0] ??= []).push(title);
        if (children) getTitles(children)
            .forEach((a, i) => (r[i + 1] ??= []).push(...a));
        return r;
    }, []),
    data = [{ title: "A", isFinal: false, children: [{ title: "AA", children: [{ title: "AAA", isFinal: true }, { title: "AAB", isFinal: true }] }, { title: "AB", children: [{ title: "ABA", isFinal: true }, { title: "ABB", isFinal: true }] }, { title: "AC", isFinal: true }] }],
    result = getTitles(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

另一种方法是分别收集标题和子项,并在函数的另一个调用中获取子项。

const
    getTitles = data => {
        const [titles, children] = getPairs(data);
        return children.length
            ? [titles, ...getTitles(children)]
            : [titles];
    },
    getPairs = data => data.reduce(
        ([t, c], { title, children = [] }) => [[...t, title], [...c, ...children]],
        [[], []]
    ),
    data = [{ title: "A", isFinal: false, children: [{ title: "AA", children: [{ title: "AAA", isFinal: true }, { title: "AAB", isFinal: true }] }, { title: "AB", children: [{ title: "ABA", isFinal: true }, { title: "ABB", isFinal: true }] }, { title: "AC", isFinal: true }] }],
    result = getTitles(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


推荐阅读