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>
Waclaw
  • 13
  • 4
  • 1
    Please explain your output – Ashik Paul Jun 12 '20 at 11:22
  • There is an error in your input "Uncaught SyntaxError: Unexpected token '}'". Please also provide code snippet of your current solution. – matvs Jun 12 '20 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. – Waclaw Jun 12 '20 at 11:32
  • @Andreas I edited and corrected syntax and naming. Thanks for spotting. – Waclaw Jun 12 '20 at 11:37
  • @matvs Added code snippet. – Waclaw Jun 12 '20 at 11:47

1 Answers1

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)
matvs
  • 1,763
  • 16
  • 26
  • No worries, I recommend you to read up on traversing the tree, especially on DFS and BFS algorithms. – matvs Jun 12 '20 at 12:12