Tengo una variedad de objetos como a continuación. Aquí el elemento child puede anidarse profundamente, también puede contener otro elemento child.
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, }], }], }];Quiero que sea una matriz plana de objetos, pero quiero agregar el nombre del padre (cuyo parentId es nulo) a todos los objetos dentro de ese padre respectivo.
Rendimiento esperado:
[ { id: 8327548, name: "001", parentId: 1234 mainParent: "Education" }, { id: 8327549, name: "002", parentId: 1234, mainParent: "Agriculture" }, // ...OTHER OBJECTS.... ]lo que he hecho hasta ahora
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; }Está dando la matriz plana de objetos, pero no puedo agregar la propiedad del nombre principal a todos los objetos.
¿Puede alguien por favor ayudarme?
Podría adoptar un enfoque recursivo y entregar el primer name encontrado como 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; }Esta es una recursión bastante limpia, que se detiene cuando no hay children en el nodo. Capturamos el valor del name que se encuentra a lo largo de la jerarquía y lo llevamos a cabo.
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}Una posible solución podría basarse completamente en una sola tarea de reduce , aunque implementada recursivamente, donde el objeto acumulado y transmitido recursivamente lleva información, el valor mainParent y el result final recopilado recursivamente...
function recursivelyReassambleAndCollectChildlessItems( { mainParent, result }, { children, ...item } ) { result = result.concat(children && children.reduce( recursivelyReassambleAndCollectChildlessItems, { // 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(recursivelyReassambleAndCollectChildlessItems, { result: [] }) .result ) .as-console-wrapper { min-height: 100%!important; top: 0; }