简体   繁体   中英

Generate flat array of objects from dynamic nested array

I have array of objects like below. Here children element may deeply nested, it may contain other children element as well.

            let response= [
                {
                    "id": 4321,
                    "name": "Education",
                    "parentId": null,
                    "children": [
                        {
                            "id": 1234,
                            "name": "category1",
                            "parentId": 4321,
                            "children": [
                                {
                                    "id": 8327548,
                                    "name": "001",
                                    "parentId": 1234
                                },
                                {
                                    "id": 8327549,
                                    "name": "002",
                                    "parentId": 1234
                                },
                            ]
                        },
                        {
                            "id": 6786,
                            "name": "Associations",
                            "parentId": 4321
                        },
                        {
                            "id": 8262439,
                            "name": "category1",
                            "parentId": 4321
                        },
                        {
                            "id": 8245,
                            "name": "Rights",
                            "parentId": 4321,
                            "children": [
                                {
                                    "id": 2447,
                                    "name": "Organizations",
                                    "parentId": 8245
                                },
                                {
                                    "id": 9525,
                                    "name": "Services",
                                    "parentId": 8245
                                },
                                {
                                    "id": 8448,
                                    "name": "Organizations",
                                    "parentId": 8245
                                }
                            ]
                        },
                        {
                            "id": 8262446,
                            "name": "Women's Rights",
                            "parentId": 4321
                        }
                    ]
                },
                {
                    "id": 21610,
                    "name": "Agriculture",
                    "parentId": null,
                    "children": [
                        {
                            "id": 3302,
                            "name": "categoryABC",
                            "parentId": 21610,
                            "children": [
                                {
                                    "id": 85379,
                                    "name": "categoryABC - General",
                                    "parentId": 3302
                                },
                                {
                                    "id": 85380,
                                    "name": "categoryABC Technology",
                                    "parentId": 3302
                                }
                            ]
                        },
                        {
                            "id": 8303,
                            "name": "Fungicides",
                            "parentId": 21610,
                            "children": [
                                {
                                    "id": 8503,
                                    "name": "Fungicides - General",
                                    "parentId": 8303
                                }
                            ]
                        },
                    ]
                },
            ];

I want to make it flat array of objects but I want to add parent name (which parentId is null) to every objects inside that respective parent.

expected output:

    [
        {
            "id": 8327548,
            "name": "001",
            "parentId": 1234
            "mainParent": "Education"
        },
        {
            "id": 8327549,
            "name": "002",
            "parentId": 1234,
            "mainParent": "Agriculture"
        },
        ...OTHER OBJECTS....
    ]

What I have done so far

        function flat(array) {
            var result = [];
            array.forEach(function (a) {
            result.push(a);
            if (Array.isArray(a.children)) {
                result = result.concat(flat(a.children));
                delete a.children;
            }
            });
            return result;
        }

It's giving the flat array of objects but I'm not able to add parent name property to every objects.

Can someone please help me?

You could take a recursive approach an handover the first found name as mainParent .

 const flat = mainParent => o => o.children ? o.children.flatMap(flat(mainParent || o.name)) : { ...o, mainParent }, response = [{ id: 4321, name: "Education", parentId: null, children: [{ id: 1234, name: "category1", parentId: 4321, children: [{ id: 8327548, name: "001", parentId: 1234 }, { id: 8327549, name: "002", parentId: 1234 }] }, { id: 6786, name: "Associations", parentId: 4321 }, { id: 8262439, name: "category1", parentId: 4321 }, { id: 8245, name: "Rights", parentId: 4321, children: [{ id: 2447, name: "Organizations", parentId: 8245 }, { id: 9525, name: "Services", parentId: 8245 }, { id: 8448, name: "Organizations", parentId: 8245 }] }, { id: 8262446, name: "Women's Rights", parentId: 4321 }] }, { id: 21610, name: "Agriculture", parentId: null, children: [{ id: 3302, name: "categoryABC", parentId: 21610, children: [{ id: 85379, name: "categoryABC - General", parentId: 3302 }, { id: 85380, name: "categoryABC Technology", parentId: 3302 }] }, { id: 8303, name: "Fungicides", parentId: 21610, children: [{ id: 8503, name: "Fungicides - General", parentId: 8303 }] }] }], result = response.flatMap(flat()); console.log(result);
 .as-console-wrapper { max-height: 100% !important; top: 0; }

This is a fairly clean recursion, stopping when there are no children in the node. We capture the first name value found along the hierarchy and carry it through.

 const flat = (xs, name = null) => xs .flatMap (x => x .children ? flat (x .children, name || x .name) : [{...x, mainParent: name}] ) const response = [{id: 4321, name: "Education", parentId: null, children: [{id: 1234, name: "category1", parentId: 4321, children: [{id: 8327548, name: "001", parentId: 1234}, {id: 8327549, name: "002", parentId: 1234}]}, {id: 6786, name: "Associations", parentId: 4321}, {id: 8262439, name: "category1", parentId: 4321}, {id: 8245, name: "Rights", parentId: 4321, children: [{id: 2447, name: "Organizations", parentId: 8245}, {id: 9525, name: "Services", parentId: 8245}, {id: 8448, name: "Organizations", parentId: 8245}]}, {id: 8262446, name: "Women's Rights", parentId: 4321}]}, {id: 21610, name: "Agriculture", parentId: null, children: [{id: 3302, name: "categoryABC", parentId: 21610, children: [{id: 85379, name: "categoryABC - General", parentId: 3302}, {id: 85380, name: "categoryABC Technology", parentId: 3302}]}, {id: 8303, name: "Fungicides", parentId: 21610, children: [{id: 8503, name: "Fungicides - General", parentId: 8303}]}]}] console .log (flat (response))
 .as-console-wrapper {max-height: 100% !important; top: 0}

A possible solution could be based entirely on a single, though recursively implemented, reduce task, where the accumulating and recursively passed down object carries both information, the mainParent value and the recursively collected final result ...

 function recursivelyReassambleAndCollectChildOnlyItems( { mainParent, result }, { children, ...item } ) { result = result.concat(children && children.reduce( recursivelyReassambleAndCollectChildOnlyItems, { // was: // mainParent: mainParent ?? item.name, /** * OP quote: * "... but I want to add parent name * (which parentId is null) to every * objects inside that respective parent." */ mainParent: item.parentId === null ? item.name : mainParent, result: [], } ).result || { mainParent, ...item }); return { mainParent, result }; } const response = [{ 'id': 4321, 'name': 'Education', 'parentId': null, 'children': [{ 'id': 1234, 'name': 'category1', 'parentId': 4321, 'children': [{ 'id': 8327548, 'name': '001', 'parentId': 1234, }, { 'id': 8327549, 'name': '002', 'parentId': 1234, }], }, { 'id': 6786, 'name': 'Associations', 'parentId': 4321, }, { 'id': 8262439, 'name': 'category1', 'parentId': 4321, }, { 'id': 8245, 'name': 'Rights', 'parentId': 4321, 'children': [{ 'id': 2447, 'name': 'Organizations', 'parentId': 8245, }, { 'id': 9525, 'name': 'Services', 'parentId': 8245, }, { 'id': 8448, 'name': 'Organizations', 'parentId': 8245, }], }, { 'id': 8262446, 'name': 'Women\\'s Rights', 'parentId': 4321, }], }, { 'id': 21610, 'name': 'Agriculture', 'parentId': null, 'children': [{ 'id': 3302, 'name': 'categoryABC', 'parentId': 21610, 'children': [{ 'id': 85379, 'name': 'categoryABC - General', 'parentId': 3302, }, { 'id': 85380, 'name': 'categoryABC Technology', 'parentId': 3302, }], }, { 'id': 8303, 'name': 'Fungicides', 'parentId': 21610, 'children': [{ 'id': 8503, 'name': 'Fungicides - General', 'parentId': 8303, }], }], }]; console.log(response .reduce(recursivelyReassambleAndCollectChildOnlyItems, { result: [] }) .result )
 .as-console-wrapper { min-height: 100%!important; top: 0; }

Less obscure, but still fairly concise.

 const response = [{ id: 4321, name: 'Education', parentId: null, children: [{ id: 1234, name: 'category1', parentId: 4321, children: [{ id: 8327548, name: '001', parentId: 1234 }, { id: 8327549, name: '002', parentId: 1234 }] }, { id: 6786, name: 'Associations', parentId: 4321 }, { id: 8262439, name: 'category1', parentId: 4321 }, { id: 8245, name: 'Rights', parentId: 4321, children: [{ id: 2447, name: 'Organizations', parentId: 8245 }, { id: 9525, name: 'Services', parentId: 8245 }, { id: 8448, name: 'Organizations', parentId: 8245 }] }, { id: 8262446, name: 'Women\\'s Rights', parentId: 4321 }] }, { id: 21610, name: 'Agriculture', parentId: null, children: [{ id: 3302, name: 'categoryABC', parentId: 21610, children: [{ id: 85379, name: 'categoryABC - General', parentId: 3302 }, { id: 85380, name: 'categoryABC Technology', parentId: 3302 }] }, { id: 8303, name: 'Fungicides', parentId: 21610, children: [{ id: 8503, name: 'Fungicides - General', parentId: 8303 }] }] }]; function flatten(arr, mainParent = null) { if (!arr) return; let result = []; for (const obj of arr) { result.push(...(flatten(obj.children, mainParent ?? obj.name) ?? [{ ...obj, mainParent }])); } return result; } console.log(flatten(response));
 .as-console-wrapper { max-height: 100% !important; top: 0; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM