繁体   English   中英

如何弄平(森林)树木?

[英]How do I flatten a (forest of) trees?

我有一片任意高度的森林,大致是这样的:

let data = [
  { "id": 2, "name": "AAA", "parent_id": null, "short_name": "A" },
  {
    "id": 10, "name": "BBB", "parent_id": null, "short_name": "B", "children": [
      {
        "id": 3, "name": "CCC", "parent_id": 10, "short_name": "C", "children": [
          { "id": 6, "name": "DDD", "parent_id": 3, "short_name": "D" },
          { "id": 5, "name": "EEE", "parent_id": 3, "short_name": "E" }
        ]
      },
      {
        "id": 4, "name": "FFF", "parent_id": 10, "short_name": "F", "children": [
          { "id": 7, "name": "GGG", "parent_id": 4, "short_name": "G" },
          { "id": 8, "name": "HHH", "parent_id": 4, "short_name": "H" }
        ]
      }]
  }
];

我正在尝试生成所有从根到叶的路径的表示,像这样

[
  [
    {
      "id": 2,
      "name": "AAA"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 3,
      "name": "C"
    },
    {
      "id": 6,
      "name": "DDD"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 3,
      "name": "C"
    },
    {
      "id": 5,
      "name": "EEE"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 4,
      "name": "F"
    },
    {
      "id": 7,
      "name": "GGG"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 4,
      "name": "F"
    },
    {
      "id": 8,
      "name": "HHH"
    }
  ]
]

所以我写了下面的代码:

function flattenTree(node, path = []) {
    if (node.children) {
        return node.children.map(child => flattenTree(child, [...path, child]));
  } else {
    let prefix = path.slice(0, path.length - 1).map(n => ({ id: n.id, name: n.short_name }));
    let last = path[path.length - 1];
    return [...prefix, { id: last.id, name: last.name } ];
  }
}

let paths = data.map(n => flattenTree(n, [n]));

但是paths带有额外的嵌套,如下所示:

[
  [
    {
      "id": 2,
      "name": "AAA"
    }
  ],
  [
    [
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 3,
          "name": "C"
        },
        {
          "id": 6,
          "name": "DDD"
        }
      ],
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 3,
          "name": "C"
        },
        {
          "id": 5,
          "name": "EEE"
        }
      ]
    ],
    [
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 4,
          "name": "F"
        },
        {
          "id": 7,
          "name": "GGG"
        }
      ],
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 4,
          "name": "F"
        },
        {
          "id": 8,
          "name": "HHH"
        }
      ]
    ]
  ]
]

我没有办法尝试解决此问题的许多方法,但是看起来算法似乎不应该产生额外的嵌套-否则我的眼神已经非常交叉,以至于如果有人卡住,我将看不到我的错误他们的手指放在上面。

有人可以帮忙吗? 随意阅读此JSFiddle https://jsfiddle.net/png7x9bh/66/

额外的嵌套由map创建。 map只是将结果包装到一个数组中并返回它们,它不在乎是否在子节点上调用它。 使用reduce ,只是concat (或push ,什么适合你的表现)的结果直接进入第一级阵列:

 let data = [{"id":2,"name":"AAA","parent_id":null,"short_name":"A"},{"id":10,"name":"BBB","parent_id":null,"short_name":"B","children":[{"id":3,"name":"CCC","parent_id":10,"short_name":"C","children":[{"id":6,"name":"DDD","parent_id":3,"short_name":"D"},{"id":5,"name":"EEE","parent_id":3,"short_name":"E"}]},{"id":4,"name":"FFF","parent_id":10,"short_name":"F","children":[{"id":7,"name":"GGG","parent_id":4,"short_name":"G"},{"id":8,"name":"HHH","parent_id":4,"short_name":"H"}]}]}]; function flattenTree(node, path = []) { let pathCopy = Array.from(path); pathCopy.push({id: node.id, name: node.name}); if(node.children) { return node.children.reduce((acc, child) => acc.concat(flattenTree(child, pathCopy)), []); } return [pathCopy]; } let result = data.reduce((result, node) => result.concat(flattenTree(node)), []); console.log(JSON.stringify(result, null, 3)); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM