TypeScript 中的递归函数 - 父数组
Posted
技术标签:
【中文标题】TypeScript 中的递归函数 - 父数组【英文标题】:Recursive Function in TypeScript - Parents Array 【发布时间】:2022-01-22 11:38:17 【问题描述】:我想创建一个递归函数来接收包含 id 和 parent_id 的对象列表。如果元素的父元素在列表中,我想将其删除并将其添加到父元素。
转换这个:
"id": 180,
"children": [],
"parent_id": 195,
"name": "Object 180"
,
"id": 193,
"children": [],
"parent_id": 180,
"name": "Object 193"
,
"id": 194,
"children": [],
"parent_id": 180,
"name": "Object 194"
"id": 199,
"children": [],
"parent_id": 187,
"name": "Object 199"
"id": 304,
"children": [],
"parent_id": 193,
"name": "Object 304"
到这里:
"id": 180,
"children": [
"id": 193,
"children": [
"id": 304,
"children": [],
"parent_id": 193,
"name": "Object 304"
],
"parent_id": 180,
"name": "Object 193"
,
"id": 194,
"children": [],
"parent_id": 180,
"name": "Object 194"
],
"parent_id": 195,
"name": "Object 180"
,
"id": 199,
"children": [],
"parent_id": 187,
"name": "Object 199"
有时parent_id为null,父母的等级没有限制。
【问题讨论】:
结果是一个数组? 【参考方案1】:因为 basarat 的回答没有考虑嵌套超过一层的项目。
这是一个创建具有任意嵌套深度的输出的解决方案:
const listToTree = (input) =>
const map = new Map(input.map((item) => [item.id, item]));
const output = [];
for (const item of input)
if (map.has(item.parent_id))
map.get(item.parent_id).children.push(map.get(item.id));
else
output.push(map.get(item.id));
return output;
;
const input = [
"id": 180,
"value": 10,
"children": [],
"parent_id": 195,
"name": "Object 180"
,
"id": 193,
"value": 10,
"children": [],
"parent_id": 180,
"name": "Object 193"
,
"id": 194,
"value": 10,
"children": [],
"parent_id": 180,
"name": "Object 194"
,
"id": 199,
"children": [],
"parent_id": 187,
"name": "Object 199"
,
"id": 304,
"value": 10,
"children": [],
"parent_id": 193,
"name": "Object 304"
,
"id": 305,
"value": 10,
"children": [],
"parent_id": 194,
"name": "Object 304"
];
const output = listToTree(input);
console.log(output);
编辑:聚合值
如果您想沿结果树的祖先链聚合值,我建议您之后在单独的函数中执行此操作。这将使您的代码更简洁、更易于测试且更具可读性。
实现取决于您的输入数组是否已排序(子项在父项之前)。如果要处理无序输入,则必须遍历每个祖先链。
function aggregateValue(branch)
const children = branch.children || [];
return children.reduce((sum, child) => sum + aggregateValue(child), branch.value || 0);
function aggregateValueAlongBranches(tree)
return tree.map((branch) =>
return
...branch,
aggregatedValue: aggregateValue(branch),
children: aggregateValueAlongBranches(branch.children),
;
);
const input = [
"id": 180,
"value": 10,
"children": [
"id": 193,
"value": 10,
"children": [
"id": 304,
"value": 10,
"children": [],
"parent_id": 193,
"name": "Object 304"
],
"parent_id": 180,
"name": "Object 193"
,
"id": 194,
"value": 10,
"children": [
"id": 305,
"value": 10,
"children": [],
"parent_id": 194,
"name": "Object 304"
],
"parent_id": 180,
"name": "Object 194"
],
"parent_id": 195,
"name": "Object 180"
,
"id": 199,
"children": [],
"parent_id": 187,
"name": "Object 199"
];
const output = aggregateValueAlongBranches(input);
console.log(output);
【讨论】:
谢谢!我在想我们需要一个递归函数。我可以在其中使用一个函数来堆叠孩子的价值吗?例如:parent_value = child_1.value + child_2.value 您的意思是为每个包含完整路径的项目添加一个附加字段?喜欢$rootItem.id.$child1.id.$child2.id
吗?使用ancestors
对树建模有一个常见的模式,请查看this。将其保存在如下字段中可能更有用:ancestors: ['root_ancestor_id', 'first_ancestor_id', 'second_ancestor_id']
。意思是,这个项目是 'second_ancestor' 的子级,它是 'first_ancestor' 的子级,后者是没有父级的 'root_ancestor' 的子级。
我的意思是,例如,家庭拥有并添加到父母的金额。例如:在列表中,祖父有 4 美元,父亲有 2 美元,儿子有 1 美元。树转换后,祖父有 7 美元,父亲有 3 美元,儿子有 1 美元。所有父母都有孩子的钱。
@WalberAmorim,最好在单独的函数中执行此操作。我添加了一个例子
感谢您的帮助!你救了我:D【参考方案2】:
您不需要递归函数。只需跟踪您已经看过的项目,如果其中存在父项,请添加到 parent.children
或添加新的根节点。
附上一个完整的解决方案示例。
完整代码
type Item =
id: number,
children: Item[],
parent_id: number,
name: string,
const items: Item[] = [
"id": 180,
"children": [],
"parent_id": 195,
"name": "Object 180"
,
"id": 193,
"children": [],
"parent_id": 180,
"name": "Object 193"
,
"id": 194,
"children": [],
"parent_id": 180,
"name": "Object 194"
,
"id": 199,
"children": [],
"parent_id": 187,
"name": "Object 199"
,
"id": 304,
"children": [],
"parent_id": 193,
"name": "Object 304"
];
function nest(items:Item[]): Item[]
const output: Item[] = [];
const idToItem = new Map<number,Item>();
for (let item of items)
// Either add to parent. Or create a new root level node
if (idToItem.has(item.parent_id))
idToItem.get(item.parent_id)!.children.push(item);
else
idToItem.set(item.id, item);
output.push(item);
return output;
console.log(nest(items));
【讨论】:
此解决方案忽略嵌套子级以上是关于TypeScript 中的递归函数 - 父数组的主要内容,如果未能解决你的问题,请参考以下文章
php写函数 根据子类(id)递归查找顶级父类(id) 返回父类名字 (表结构:id name pid)