0

I have an array:

[ 
  { id: 1, 
    name: "parent1", 
    children: [ 
               { id: 10, 
                 name: "first_child_of_id_1", 
                 children: [ 
                            { id: 100, name: "child_of_id_10", children: []},
                            { id: 141, name: "child_of_id_10", children: []}, 
                            { id: 155, name: "child_of_id_10", children: []}
                           ]
               },
               { id: 42, 
                 name: "second_child_of_id_1", 
                 children: [ 
                            { id: 122, name: "child_of_id_42", children: []},
                            { id: 133, name: "child_of_id_42", children: []}, 
                            { id: 177, name: "child_of_id_42", children: []}
                           ]
               }
             ]
  },
  { id: 7, 
    name: "parent7", 
    children: [ 
               { id: 74, 
                 name: "first_child_of_id_7", 
                 children: [ 
                            { id: 700, name: "child_of_id_74", children: []},
                            { id: 732, name: "child_of_id_74", children: []}, 
                            { id: 755, name: "child_of_id_74", children: []}
                           ]
               },
               { id: 80, 
                 name: "second_child_of_id_7", 
                 children: [ 
                            { id: 22, name: "child_of_id_80", children: []},
                            { id: 33, name: "child_of_id_80", children: []}, 
                            { id: 77, name: "child_of_id_80", children: []}
                           ]
               }
             ]
  }
] 

What I need is an array of arrays like this:

[
  [ "id", "name", "parent_id", "parent_name" ],
  [  1, "parent1", null, "" ],
  [ 10, "first_child_of_id_1", 1, "parent1"],
  [ 42, "second_child_of_id_1", 1, "parent1"],
  [100, "child_of_id_10", 10, "first_child_of_id_1"]
]

and so on for all nested objects for me to convert them into CSV rows. I've checked many answers and found a similar problem here: How to convert array of nested objects to CSV? But it produces too long rows for many nested objects and I am not experienced enough with JavaScript to modify map function.

const categories = [ 
                { id: 1, 
                name: "parent1", 
                children: [ 
                            { id: 10, 
                            name: "first_child_of_id_1", 
                            children: [ 
                                        { id: 100, name: "child_of_id_10", children: []},
                                        { id: 141, name: "child_of_id_10", children: []}, 
                                        { id: 155, name: "child_of_id_10", children: []}
                                        ]
                            },
                            { id: 42, 
                            name: "second_child_of_id_1", 
                            children: [ 
                                        { id: 122, name: "child_of_id_42", children: []},
                                        { id: 133, name: "child_of_id_42", children: []}, 
                                        { id: 177, name: "child_of_id_42", children: []}
                                        ]
                            }
                        ]
                },
                { id: 7, 
                name: "parent7", 
                children: [ 
                            { id: 74, 
                            name: "first_child_of_id_7", 
                            children: [ 
                                        { id: 700, name: "child_of_id_74", children: []},
                                        { id: 732, name: "child_of_id_74", children: []}, 
                                        { id: 755, name: "child_of_id_74", children: []}
                                        ]
                            },
                            { id: 80, 
                            name: "second_child_of_id_7", 
                            children: [ 
                                        { id: 22, name: "child_of_id_80", children: []},
                                        { id: 33, name: "child_of_id_80", children: []}, 
                                        { id: 77, name: "child_of_id_80", children: []}
                                        ]
                            }
                        ]
                }
            ] 


    function pivot(arr) {
        var mp = new Map();

        function setValue(a, path, val) {
            if (Object(val) !== val) { // primitive value
                var pathStr = path.join('.');
                var i = (mp.has(pathStr) ? mp : mp.set(pathStr, mp.size)).get(pathStr);
                a[i] = val;
            } else {
                for (var key in val) {
                    setValue(a, key == '0' ? path : path.concat(key), val[key]);
                }
            }
            return a;
        }

        var result = arr.map(obj => setValue([], [], obj));
        return [[...mp.keys()], ...result];
    }


    function toCsv(arr) {
        return arr.map(row =>
            row.map(val => isNaN(val) ? JSON.stringify(val) : +val).join(',')
        ).join('\n');
    }
<button onclick="console.log(toCsv(pivot(categories)))">Output</button>

5
  • 1
    Please explain your output Commented Jun 12, 2020 at 11:22
  • There is an error in your input "Uncaught SyntaxError: Unexpected token '}'". Please also provide code snippet of your current solution. Commented Jun 12, 2020 at 11:30
  • First array with names is for you to know how the structure looks like. First display id of element, name of element, parent id (if exist), parent name (if exist). Next arrays - go to child element and display the same "id", "name", "parent id", "parent name". Go to child of the child element do the same... And so on for all nested childrens of childrens. Commented Jun 12, 2020 at 11:32
  • @Andreas I edited and corrected syntax and naming. Thanks for spotting. Commented Jun 12, 2020 at 11:37
  • @matvs Added code snippet. Commented Jun 12, 2020 at 11:47

1 Answer 1

0

Simple DFS or BFS algorithm should do the job here. The difference is the order of created "rows".
If you want to have all children of given node listed immediately after their parent, then you need to use BFS.

Example with DFS and BFS:

const input = [{
        id: 1,
        name: "parent1",
        children: [{
                id: 10,
                name: "first_child_of_id_1",
                children: [{
                        id: 100,
                        name: "child_of_id_10",
                        children: []
                    },
                    {
                        id: 141,
                        name: "child_of_id_10",
                        children: []
                    },
                    {
                        id: 155,
                        name: "child_of_id_10",
                        children: []
                    }
                ]
            },
            {
                id: 42,
                name: "second_child_of_id_1",
                children: [{
                        id: 122,
                        name: "child_of_id_42",
                        children: []
                    },
                    {
                        id: 133,
                        name: "child_of_id_42",
                        children: []
                    },
                    {
                        id: 177,
                        name: "child_of_id_42",
                        children: []
                    }
                ]
            }
        ]
    },
    {
        id: 7,
        name: "parent7",
        children: [{
                id: 74,
                name: "first_child_of_id_7",
                children: [{
                        id: 700,
                        name: "child_of_id_74",
                        children: []
                    },
                    {
                        id: 732,
                        name: "child_of_id_74",
                        children: []
                    },
                    {
                        id: 755,
                        name: "child_of_id_74",
                        children: []
                    }
                ]
            },
            {
                id: 80,
                name: "second_child_of_id_1",
                children: [{
                        id: 22,
                        name: "child_of_id_80",
                        children: []
                    },
                    {
                        id: 33,
                        name: "child_of_id_80",
                        children: []
                    },
                    {
                        id: 77,
                        name: "child_of_id_80",
                        children: []
                    }
                ]
            }
        ]
    }
]

//DFS
function deepWalk(node, parent, output = []) {
    if (!node || typeof node !== 'object' || !node.id) return;

    output.push([node.id, node.name, parent ? parent.id : null, parent ? parent.name : ""])
    if (node.children) {
        for (const child of node.children) {
            deepWalk(child, node, output);
        }
    }

    return output;
}

//BFS
function broadWalk(root) {
    const output = []
    const queue = [];
    queue.push({
        node: root,
        parent: null
    });
    while (queue.length) {
        const {
            node,
            parent
        } = queue.shift();
        output.push([node.id, node.name, parent ? parent.id : null, parent ? parent.name : ""])
        if (node.children) {
            for (const child of node.children) {
                queue.push({
                    node: child,
                    parent: node
                });
            }
        }
    }
    return output;
}




let rowsDfs = [
    ["id", "name", "parent_id", "parent_name"]
];
let rowsBfs = [
    ["id", "name", "parent_id", "parent_name"]
];
for (const node of input) {
    rowsDfs = [...rowsDfs, ...deepWalk(node)];
    rowsBfs = [...rowsBfs, ...broadWalk(node)];

}

console.log("rows DFS: ", rowsDfs)
console.log("rows BFS: ", rowsBfs)

Sign up to request clarification or add additional context in comments.

1 Comment

No worries, I recommend you to read up on traversing the tree, especially on DFS and BFS algorithms.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.