[付费问答] 在写一个富文本编辑器,其中用到了带父子节点的双向链表,可无限嵌套,写了个递归一直报错,希望大佬指点指点,答案被采纳我 v 信转 120 给您(不在乎钱的也可以试一试,这十分考验算法实战能力)

查看 20|回复 0
作者:matrixage   
在写一个富文本编辑器,其中用到了带父子节点的双向链表,要把无顺序的节点树根据 prev_id ,next_id 处理成顺序的,而且有些节点是带 children 的,children 中的节点同其他节点,可无限嵌套,写了个递归一直报错,希望大佬指点指点,答案被采纳我 v 信转 120 给您(不在乎钱的也可以试一试,这十分考验算法实战能力)
raw_nodes 数据:
const raw_nodes = [
    {
        "type": "file",
        "name": "工作目录二",
        "icon": "",
        "id": "dgacbecjhzbcufq13_rvmr_gjz98xo",
        "module": "todo",
        "pid": "kzoxuadlnqrtxeg43xugw2s0voutnj",
        "prev_id": "pcwsejrnwzuwjpyve64ww68hxxt74r"
    },
    {
        "type": "file",
        "name": "日常",
        "icon": "",
        "id": "gpvwcojxffgijtw14xat7-ealc7w8l",
        "module": "todo",
        "pid": "",
        "prev_id": "kzoxuadlnqrtxeg43xugw2s0voutnj"
    },
    {
        "type": "dir",
        "name": "工作",
        "icon": "",
        "id": "kzoxuadlnqrtxeg43xugw2s0voutnj",
        "module": "todo",
        "pid": "",
        "next_id": "gpvwcojxffgijtw14xat7-ealc7w8l"
    },
    {
        "type": "file",
        "name": "工作目录一",
        "icon": "",
        "id": "pcwsejrnwzuwjpyve64ww68hxxt74r",
        "module": "todo",
        "pid": "kzoxuadlnqrtxeg43xugw2s0voutnj",
        "next_id": "kzoxuadlnqrtxeg43xugw2s0voutnj"
    }
]
tree 数据和 tree_map 由下面 class 中的函数可计算出来:
class 的一部分:
import { get, flatMap, last, initial, cloneDeep, find } from 'lodash-es'
type RawNode = {
        id: string
        pid?: string
        prev_id?: string
        next_id?: string
        [key: string]: any
}
type RawNodes = Array
type TreeItem = RawNode & { children?: Tree }
type Tree = Array[Tr]
type TreeMap = Record
export default class Index {
        tree = [] as Tree
        public init(raw_nodes: RawNodes) {
                const raw_tree_map = this.setRawMap(raw_nodes)
                const { tree, tree_map } = this.getTree(raw_nodes, raw_tree_map)
                console.log(tree)
                this.tree = this.sortTree(tree, tree_map)
        }
        private setRawMap(raw_nodes: RawNodes) {
                const tree_map = {} as TreeMap
                raw_nodes.map((item) => {
                        tree_map[item.id] = item
                })
                return tree_map
        }
        private getTree(raw_nodes: RawNodes, tree_map: TreeMap) {
                const tree = [] as Tree
                raw_nodes.forEach((item) => {
                        if (item.pid) {
                                if (!tree_map[item.pid].children) {
                                        tree_map[item.pid].children = []
                                }
                                if (!tree_map[item.pid]?.children?.length) {
                                        tree_map[item.pid].children = [item]
                                } else {
                                        tree_map[item.pid].children.push(item)
                                }
                        } else {
                                tree.push(item)
                        }
                })
                return { tree, tree_map }
        }
        private sortTree(tree: Tree, tree_map: TreeMap) {
                const target_tree = [] as Tree
                const start_node = find(tree, (item) => !item.prev_id)
                if (!start_node) return []
                let current = start_node.id
                while (current) {
                        const item = tree_map[current]
                        if (item?.children?.length) {
                                // 这里报错( RangeError: Maximum call stack size exceeded )
                                // item.children = this.sortTree(item.children, tree_map)
                        }
                        target_tree.push(item)
                        current = item.next_id
                }
                return target_tree
        }
}
正确的情况应输出数据为:
const tree = [
    {
        "type": "dir",
        "name": "工作",
        "icon": "",
        "id": "kzoxuadlnqrtxeg43xugw2s0voutnj",
        "module": "todo",
        "pid": "",
        "next_id": "gpvwcojxffgijtw14xat7-ealc7w8l",
        "children": [
             {
                "type": "file",
                "name": "工作目录一",
                "icon": "",
                "id": "pcwsejrnwzuwjpyve64ww68hxxt74r",
                "module": "todo",
                "pid": "kzoxuadlnqrtxeg43xugw2s0voutnj",
                "next_id": "kzoxuadlnqrtxeg43xugw2s0voutnj"
            },
            {
                "type": "file",
                "name": "工作目录二",
                "icon": "",
                "id": "dgacbecjhzbcufq13_rvmr_gjz98xo",
                "module": "todo",
                "pid": "kzoxuadlnqrtxeg43xugw2s0voutnj",
                "prev_id": "pcwsejrnwzuwjpyve64ww68hxxt74r"
            },
           
        ]
    },
      {
        "type": "file",
        "name": "日常",
        "icon": "",
        "id": "gpvwcojxffgijtw14xat7-ealc7w8l",
        "module": "todo",
        "pid": "",
        "prev_id": "kzoxuadlnqrtxeg43xugw2s0voutnj"
    },
]
哪位大佬指点迷津,小弟 v 您 60+60 ,祝您 66 大顺!
您需要登录后才可以回帖 登录 | 立即注册

返回顶部