Tengo un objeto recursivo de la estructura:
const obj = { name: 'entity-0', children: [{ name: 'entity-0-0', children: [] }, { name: 'entity-0-1', children: [{ name: 'entity-1-0', children: [] }] }] }Y actualmente lo estoy convirtiendo en una matriz plana como esta:
const arr = []; function convertObjToArr(obj, level, parent) { arr.push({ name: obj.name, parent: parent?.name, level }); obj.children.forEach(v => this.convertObjToArr(v, level + 1, obj)); } convertObjToArr(obj, 0);Esto da como resultado una matriz que se ve así:
[ { name: 'entity-0', level: 0 }, { name: 'entity-0-0', parent: 'entity-0', level: 1 }, { name: 'entity-0-1', parent: 'entity-0', level: 1 }, { name: 'entity-1-0', parent: 'entity-0-1', level: 2} ] Lo que ahora tengo que hacer es revertir el proceso. Donde doy el arr generado como entrada y obtengo obj como salida. es posible? ¿Cómo haría esto?
Esto es hasta donde he llegado:
function convertArrToObj(iArr) { for(let i = 0; i < iArr.length; i++) { if(!iArr[i].parent) newObj = { ...iArr[i], children: [] }; else { // this should somehow find iArr[i].parent and insert itself into its children array } } }Pero como puede ver, está incompleto y estoy bastante seguro de que no será recursivo, así que si tiene más de 1 capa de profundidad, no funcionará, no lo creo.
Podría tomar un solo bucle y construir una nueva estructura.
const getTree = (data, root) => { const t = {}; data.forEach(({ name, parent }) => ((t[parent] ??= {}).children ??= []).push(Object.assign(t[name] ??= {}, { name })) ); return t[root].children; }, data = [{ name: "entity-0", parent: undefined, level: 0 }, { name: "entity-0-0", parent: "entity-0", level: 1 }, { name: "entity-0-1", parent: "entity-0", level: 1 }, { name: "entity-1-0", parent: "entity-0-1", level: 2 }], tree = getTree(data); console.log(tree); .as-console-wrapper { max-height: 100% !important; top: 0; }Esto podría funcionar.
Si hay una sola raíz, tome el primer elemento en la matriz de resultados.
const arr = [ { name: 'entity-0', level: 0 }, { name: 'entity-0-0', parent: 'entity-0', level: 1 }, { name: 'entity-0-1', parent: 'entity-0', level: 1 }, { name: 'entity-1-0', parent: 'entity-0-1', level: 2} ]; const convertArrToObj = (arr, parent) => { return arr.filter(item => item.parent === parent) .reduce((acc, item) => { acc.push({name: item.name, children: convertArrToObj(arr, item.name)}); return acc; }, []); }; const result = convertArrToObj(arr); console.log(result); // using map is simpler, advised by Nick Parsons const convertArrToObj2 = (arr, parent) => { return arr.filter(item => item.parent === parent) .map(item => ({name: item.name, children: convertArrToObj2(arr, item.name)})); }; console.log(convertArrToObj2(arr));