javascriptrecursionecmascript-6orgchart

Generate a flat array of ids from a multilevel tree using reduce function with recursion?


I am trying to implement a user hierarchy using the js library orgChart. by getHierarchy() method in the library is outputting a object like the following.

var datascource = {
            "id": "1",
            "children": [{
                "id": "2"
            }, {
                "id": "3",
                "children": [{
                    "id": "4"
                }, {
                    "id": "5",
                    "children": [{
                        "id": "6"
                    }, {
                        "id": "7"
                    }]
                }]
            }, {
                "id": "10"
            }, {
                "id": "12"
            }]
        };

I want to generate flat array from ids in the tree. ex: //["1", "2", "3", "4", "5", "6", "7", "10", "12"]

I came up with,

function getNestedArraysOfIds(node) {
    if (node.children == undefined) {
        return [node.id];
    } else {
        return [node.id,...node.children.map(subnode => (subnode.children==undefined) ? subnode.id: getNestedArraysOfIds(subnode))];
    }
}

function getIds(array) {
        return array.reduce((acc, subArray) =>
            (Array.isArray(subArray)) ? [...acc, ...getIds(subArray)] : [...acc, subArray]);
    }

var idArrays = getNestedArraysOfIds(datascource );
var ids = getIds(idArrays); //["1", "2", "3", "4", "5", "6", "7", "10", "12"]

I have try to do it with single reduce function but I end up writing two functions both of them are recursive. Is there much elegant and effective way to do it with single reduce function?

Thank you in advance.


Solution

  • You could flat the children by taking a mapping with concat.

    function getFlat({ id, children = [] }) {
        return [id].concat(...children.map(getFlat));
    }
    
    var data = { id: "1", children: [{ id: "2" }, { id: "3", children: [{ id: "4" }, { id: "5", children: [{ id: "6" }, { id: "7" }] }] }, { id: "10" }, { id: "12" }] };
    
    console.log(getFlat(data));

    Same with a reduce function

    function getFlat({ id, children = [] }) {
        return children.reduce((r, o) => [...r, ...getFlat(o)], [id]);
    }
    
    var data = { id: "1", children: [{ id: "2" }, { id: "3", children: [{ id: "4" }, { id: "5", children: [{ id: "6" }, { id: "7" }] }] }, { id: "10" }, { id: "12" }] };
    
    console.log(getFlat(data));