在 javascript 中使用 map 函数进行递归
Recursion with map function in javascript
我有一张这样的地图,代表一个图形:
Map(5) {
1 => [ 2, 3 ],
2 => [ 7, 8, 10 ],
3 => [ 4 ],
10 => [ 12 ],
4 => [ 11 ]
}
我有这个 class,它创建了一个有根树:
class RootedTree {
constructor (data, ...descendants) {
this.data = data;
this.descendants = descendants;
}
}
我的目标是:给定一个根,我想将该图转换为有根树。对于上面的示例,使用 1 作为根,我想要以下 return:
const RT = (...args) => new RootedTree(...args) // just to simplify
// goal return:
RT(1, RT(2, RT(7), RT(8), RT(10, RT(12))), RT(3, RT(4, RT(11)), RT(5))
这是我的代码:
let local_descendants = []
const toRT = (root, node_map) => {
rt = new RootedTree(root)
if (node_map.get(root) !== undefined){
node_map.get(root).map((node) => toRT(node, node_map), local_descendants)
} else {
return null
}
return local_descendants
}
rt = new RootedTree(1, toRT(1, map))
我从 toRT 函数收到一个空数组。我想我可能搞砸了变量,但我不知道如何修复它。
在每次递归调用时,您可以 return 一个 RootedTree
的实例,将 root
参数作为 data
,随后的递归调用作为 descendants
:
var m = {1:[ 2, 3 ], 2:[ 7, 8, 10 ], 3:[ 4 ], 10:[ 12 ], 4:[ 11 ]}
class RootedTree {
constructor (data, ...descendants) {
this.data = data;
this.descendants = descendants;
}
display(){
return this.descendants.length === 0 ? `RT(${this.data})` : `RT(${this.data}, ${this.descendants.map(x => x.display()).join(', ')})`
}
}
function toRT(root = 1){
return (new RootedTree(root, ...(root in m ? m[root] : []).map(toRT)))
}
console.log(toRT().display())
输出:
RT(1, RT(2, RT(7), RT(8), RT(10, RT(12))), RT(3, RT(4, RT(11))))
@Ajax 的回答很好,但是您提到您有一个 Map,并希望该 Map 实例成为 toRT
的参数(好!)。
那么代码就是:
class RootedTree {
constructor (data, ...descendants) {
this.data = data;
this.descendants = descendants;
}
}
const toRT = (data, map) =>
new RootedTree(data, ...map.get(data)?.map(child => toRT(child, map))??[]);
const map = new Map([[1,[2,3]],[2,[7,8,10]],[3,[4]],[10,[12]],[4,[11]]]);
const root = toRT(1, map);
console.log(root);
说明
从您的问题可以看出您对 Map 和 spread 语法很满意,所以让我们关注这个表达式:
map.get(data)?.map(child => toRT(child, map))??[]
optional chaining operator,即 ?.
,将确保 .map()
仅在定义 map.get(data)
时调用。否则将使用 undefined
而不是 .map()
结果。
.map()
将迭代在 data
的 Map 条目中找到的子值,并通过调用 toRT(child, map)
转换它们中的每一个。后者将 return 一个 RootedTree
实例,因此 .map()
调用将 return 此类实例的数组,它们将作为我们节点的 descendants
正在建设 data
.
最后,Nullish coalescing operator,即 ??
,会将 undefined
值(来自 map.get()
)转换为空数组。这样,传播运算符在那种情况下也能正常工作。
因此首先创建更深的节点,为外部 new RootedTree
调用提供 descendants
参数。根节点是最后创建的。
我有一张这样的地图,代表一个图形:
Map(5) {
1 => [ 2, 3 ],
2 => [ 7, 8, 10 ],
3 => [ 4 ],
10 => [ 12 ],
4 => [ 11 ]
}
我有这个 class,它创建了一个有根树:
class RootedTree {
constructor (data, ...descendants) {
this.data = data;
this.descendants = descendants;
}
}
我的目标是:给定一个根,我想将该图转换为有根树。对于上面的示例,使用 1 作为根,我想要以下 return:
const RT = (...args) => new RootedTree(...args) // just to simplify
// goal return:
RT(1, RT(2, RT(7), RT(8), RT(10, RT(12))), RT(3, RT(4, RT(11)), RT(5))
这是我的代码:
let local_descendants = []
const toRT = (root, node_map) => {
rt = new RootedTree(root)
if (node_map.get(root) !== undefined){
node_map.get(root).map((node) => toRT(node, node_map), local_descendants)
} else {
return null
}
return local_descendants
}
rt = new RootedTree(1, toRT(1, map))
我从 toRT 函数收到一个空数组。我想我可能搞砸了变量,但我不知道如何修复它。
在每次递归调用时,您可以 return 一个 RootedTree
的实例,将 root
参数作为 data
,随后的递归调用作为 descendants
:
var m = {1:[ 2, 3 ], 2:[ 7, 8, 10 ], 3:[ 4 ], 10:[ 12 ], 4:[ 11 ]}
class RootedTree {
constructor (data, ...descendants) {
this.data = data;
this.descendants = descendants;
}
display(){
return this.descendants.length === 0 ? `RT(${this.data})` : `RT(${this.data}, ${this.descendants.map(x => x.display()).join(', ')})`
}
}
function toRT(root = 1){
return (new RootedTree(root, ...(root in m ? m[root] : []).map(toRT)))
}
console.log(toRT().display())
输出:
RT(1, RT(2, RT(7), RT(8), RT(10, RT(12))), RT(3, RT(4, RT(11))))
@Ajax 的回答很好,但是您提到您有一个 Map,并希望该 Map 实例成为 toRT
的参数(好!)。
那么代码就是:
class RootedTree {
constructor (data, ...descendants) {
this.data = data;
this.descendants = descendants;
}
}
const toRT = (data, map) =>
new RootedTree(data, ...map.get(data)?.map(child => toRT(child, map))??[]);
const map = new Map([[1,[2,3]],[2,[7,8,10]],[3,[4]],[10,[12]],[4,[11]]]);
const root = toRT(1, map);
console.log(root);
说明
从您的问题可以看出您对 Map 和 spread 语法很满意,所以让我们关注这个表达式:
map.get(data)?.map(child => toRT(child, map))??[]
optional chaining operator,即 ?.
,将确保 .map()
仅在定义 map.get(data)
时调用。否则将使用 undefined
而不是 .map()
结果。
.map()
将迭代在 data
的 Map 条目中找到的子值,并通过调用 toRT(child, map)
转换它们中的每一个。后者将 return 一个 RootedTree
实例,因此 .map()
调用将 return 此类实例的数组,它们将作为我们节点的 descendants
正在建设 data
.
最后,Nullish coalescing operator,即 ??
,会将 undefined
值(来自 map.get()
)转换为空数组。这样,传播运算符在那种情况下也能正常工作。
因此首先创建更深的节点,为外部 new RootedTree
调用提供 descendants
参数。根节点是最后创建的。