No puedo entender cómo explicar esto bien, pero quiero hacer una función que tome esta matriz:
const tasks = [ {id: 1, goal: 'Clean apartment', parent_id: null}, {id: 2, goal: 'Clean bathroom', parent_id: 1}, {id: 3, goal: 'Clean kitchen', parent_id: 1}, {id: 4, goal: 'Clean sink', parent_id: 2}, {id: 5, goal: 'Clean shower', parent_id: 2}, {id: 6, goal: 'Make app', parent_id: null} ]y genera este objeto:
{id: 1, goal: 'Clean apartment', parent_id: null, children: [ {id: 2, goal: 'Clean bathroom', parent_id: 1, children: [ {id: 4, goal: 'Clean sink', parent_id: 2, children: []}, {id: 5, goal: 'Clean shower', parent_id: 2, children: []}, ]}, {id: 3, goal: 'Clean kitchen', parent_id: 1, children: []}, ]}, {id: 6, goal: 'Make app', parent_id: null, children: []}Editar: Hasta ahora hice esto, pero solo devuelve la primera capa de los niños:
function addChildren(tasks, id) { var task = tasks.find(task => task.id === id) var children = tasks.filter(task => task.parent_id === id) task.children = children return task } var newTask = addChildren(tasks, 1) console.log(newTask)EDIT 2: Intenté hacer que la función sea recursiva, pero aparece un error que dice "tasks.find is not a function".
function addChildren(tasks, id) { var task = tasks.find(task => task.id === id) var children = tasks.filter(task => task.parent_id === id) task.children = children task.children.forEach(child => { addChildren(child, child.id) }) return task } var newTask = addChildren(tasks, 1) console.log(newTask)Haga que la función sea recursiva y llámela para cada niño.
const tasks = [ {id: 1, goal: 'Clean apartment', parent_id: null}, {id: 2, goal: 'Clean bathroom', parent_id: 1}, {id: 3, goal: 'Clean kitchen', parent_id: 1}, {id: 4, goal: 'Clean sink', parent_id: 2}, {id: 5, goal: 'Clean shower', parent_id: 2}, {id: 6, goal: 'Make app', parent_id: null} ] function addChildren(tasks, idOrTask) { var task = (typeof idOrTask === 'number') ? tasks.find(task => task.id === idOrTask) : idOrTask; var children = tasks.filter(t => t.parent_id === task.id); task.children = children.map(child => addChildren(tasks, child)); return task } var newTask = addChildren(tasks, 1) console.log(newTask) He optimizado un poco la función para evitar llamadas innecesarias de find .
Puede filtrar aquellos que coincidan con una identificación determinada y calcular sus hijos con una llamada recursiva:
const nest = (xs, parent = null) => xs .filter (({parent_id}) => parent_id == parent) .map (({id, ...rest}) => ({id, ...rest, children: nest (xs, id)})) const tasks = [{id: 1, goal: 'Clean apartment', parent_id: null}, {id: 2, goal: 'Clean bathroom', parent_id: 1}, {id: 3, goal: 'Clean kitchen', parent_id: 1}, {id: 4, goal: 'Clean sink', parent_id: 2}, {id: 5, goal: 'Clean shower', parent_id: 2}, {id: 6, goal: 'Make app', parent_id: null}] console .log (nest (tasks)) .as-console-wrapper {max-height: 100% !important; top: 0} Si ya no desea el parent_id ahora redundante en la salida, simplemente puede eliminarlo reemplazando la línea del map anterior con:
.map (({id, parent_id, ...rest}) => ({id, ...rest, children: nest (xs, id)})) const tasks = [ {id: 1, goal: 'Clean apartment', parent_id: null}, {id: 2, goal: 'Clean bathroom', parent_id: 1}, {id: 3, goal: 'Clean kitchen', parent_id: 1}, {id: 4, goal: 'Clean sink', parent_id: 2}, {id: 5, goal: 'Clean shower', parent_id: 2}, {id: 6, goal: 'Make app', parent_id: null} ] function buildTree(root) { return { goal: root.goal, // Store the goal children: tasks .filter(task => task.parent_id === root.id) // All tasks with parent_id = root.id .map(child => buildTree(child)) // Recursively collect their children } } const result = buildTree(tasks[0]) // Build the tree starting with 'Clean apartment' console.log(result);Puede simplificar un poco la lógica al no pasar las identificaciones