用JavaScript递归构建树

时间:2019-05-31 05:19:43

标签: javascript algorithm recursion

我正在尝试从一系列对象中递归构建一棵树。我目前正在使用.container { display:flex; justify-content: center; } 方法来遍历数组中的项目,并找出属于特定项目的子项并将其填充,然后递归地填充这些子项的子项,依此类推。但是,我无法将最后一个节点(例如,在这种情况下为波斯和暹罗)放入数组(请参见下面的预期和当前输出)

reduce()

预期输出:

    let categories = [
        { id: 'animals', parent: null },
        { id: 'mammals', parent: 'animals' },
        { id: 'cats', parent: 'mammals' },
        { id: 'dogs', parent: 'mammals' },
        { id: 'chihuahua', parent: 'dogs' },
        { id: 'labrador', parent: 'dogs' },
        { id: 'persian', parent: 'cats' },
        { id: 'siamese', parent: 'cats' }
    ];

   const reduceTree = (categories, parent = null) => 
    categories.reduce(
        (tree, currentItem) => {

            if(currentItem.parent == parent){
               tree[currentItem.id] = reduceTree(categories, currentItem.id);  
            }              

            return tree;
        },
        {}        
   )  

   console.log(JSON.stringify(reduceTree(categories), null, 1));

当前输出:

{
    "animals": {
        "mammals": {
            "cats": [     // <-- an array of cat strings
                "persian",
                "siamese"
            ],
            "dogs": [     // <-- an array of dog strings
                "chihuahua",
                "labrador"
            ]
        }
    }
}

我应该如何解决问题?

2 个答案:

答案 0 :(得分:2)

如果节点没有子节点,我将条件合并为数组。试试这个

let categories = [
        { id: 'animals', parent: null },
        { id: 'mammals', parent: 'animals' },
        { id: 'cats', parent: 'mammals' },
        { id: 'dogs', parent: 'mammals' },
        { id: 'chihuahua', parent: 'dogs' },
        { id: 'labrador', parent: 'dogs' },
        { id: 'persian', parent: 'cats' },
        { id: 'siamese', parent: 'cats' }
    ];

   const reduceTree = (categories, parent = null) => 
    categories.reduce(
        (tree, currentItem) => {

            if(currentItem.parent == parent){
                let val = reduceTree(categories, currentItem.id);
                if( Object.keys(val).length == 0){
                    Object.keys(tree).length == 0 ? tree = [currentItem.id] : tree.push(currentItem.id);
                }
                else{
                    tree[currentItem.id] = val;
                }
            } 
            return tree;
        },
        {}
   )  

   console.log(JSON.stringify(reduceTree(categories), null, 1));
注意:如果您的数据结构再次更改,则此解析器在某些其他情况下可能会失败。

答案 1 :(得分:2)

这是没有递归的解决方案:

const categories = [{ id: 'animals', parent: null },{ id: 'mammals', parent: 'animals' },{ id: 'cats', parent: 'mammals' },{ id: 'dogs', parent: 'mammals' },{ id: 'chihuahua', parent: 'dogs' },{ id: 'labrador', parent: 'dogs' },{ id: 'persian', parent: 'cats' },{ id: 'siamese', parent: 'cats' }];

// Create properties for the parents (their values are empty objects)
let res = Object.fromEntries(categories.map(({parent}) => [parent, {}]));
// Overwrite the properties for the parents of leaves to become arrays
categories.forEach(({id, parent}) => res[id] || (res[parent] = []));
// assign children to parent property, either as property of parent object or as array entry in it
categories.forEach(({id, parent}) => res[parent][res[id] ? id : res[parent].length] = res[id] || id);
// Extract the tree for the null-entry:
res = res.null;

console.log(res);