递归循环构建 object
Recursive loop to build object
我不知道如何正确解释这一点,但我想创建一个接受这个数组的函数:
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}
]
并生成此 object:
{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: []}
编辑:
到目前为止我做了这个,但它只 returns 第一层 children:
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)
编辑 2:
我尝试使函数递归,但出现错误消息“tasks.find 不是函数”。
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)
使函数递归并为每个child调用它。
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)
我对函数做了一些优化,以避免不必要的调用 find
。
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);
您可以通过不传递 ID 来稍微简化逻辑
您可以过滤那些匹配给定 ID 的那些,并通过递归调用计算它们的 children:
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}
如果您不再需要输出中的 now-redundant parent_id
,只需将上面的 map
行替换为:
即可将其删除
.map (({id, parent_id, ...rest}) => ({id, ...rest, children: nest (xs, id)}))
为什么要求递归?可以用这种迭代方式
function buildTree(tasks) {
const tasksById = tasks.reduce((acc, task) => ({
...acc,
[task.id]: { ...task }
}), {})
return Object.values(tasksById).reduce((tree, task) => {
const parent = tasksById[task.parent_id]
if (!parent) {
return tree.concat(task)
}
parent.children = parent.children || []
parent.children.push(task)
return tree
}, [])
}
我不知道如何正确解释这一点,但我想创建一个接受这个数组的函数:
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}
]
并生成此 object:
{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: []}
编辑: 到目前为止我做了这个,但它只 returns 第一层 children:
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)
编辑 2: 我尝试使函数递归,但出现错误消息“tasks.find 不是函数”。
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)
使函数递归并为每个child调用它。
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)
我对函数做了一些优化,以避免不必要的调用 find
。
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);
您可以通过不传递 ID 来稍微简化逻辑
您可以过滤那些匹配给定 ID 的那些,并通过递归调用计算它们的 children:
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}
如果您不再需要输出中的 now-redundant parent_id
,只需将上面的 map
行替换为:
.map (({id, parent_id, ...rest}) => ({id, ...rest, children: nest (xs, id)}))
为什么要求递归?可以用这种迭代方式
function buildTree(tasks) {
const tasksById = tasks.reduce((acc, task) => ({
...acc,
[task.id]: { ...task }
}), {})
return Object.values(tasksById).reduce((tree, task) => {
const parent = tasksById[task.parent_id]
if (!parent) {
return tree.concat(task)
}
parent.children = parent.children || []
parent.children.push(task)
return tree
}, [])
}