recursion - 如何在递归更改可变结构时避免克隆部分
问题描述
我尝试递归地穿过一棵玫瑰树。以下代码也可以按预期工作,但由于借用检查器的问题,我仍然需要克隆值。因此,如果有办法从克隆变为更好的东西,那就太好了。
没有 clone() rust 抱怨(正确地)我通过查看子节点和闭包中的第二次来借用自我可变。
整个结构和代码比下面显示的更复杂和更大,但这是核心元素。我是否必须更改数据结构或者我错过了一些明显的东西?如果数据结构是问题,您将如何更改它?
此外,NType 枚举在这里似乎有点没用,但我还有一些其他类型需要考虑。这里内部节点总是有子节点,而外部节点永远不会。
enum NType{
Inner,
Outer
}
#[derive(Eq, PartialEq, Clone, Debug)]
struct Node {
// isn't a i32 actually. In my real program it's another struct
count: i32,
n_type: NType,
children: Option<Vec<usize>>
}
#[derive(Eq, PartialEq, Clone, Debug)]
struct Tree {
nodes: Vec<Node>,
}
impl Tree{
pub fn calc(&mut self, features: &Vec<i32>) -> i32{
// root is the last node
self.calc_h(self.nodes.len() - 1, features);
self.nodes[self.nodes.len() - 1].count.clone()
}
fn calc_h(&mut self, current: usize, features: &Vec<i32>){
// do some other things to decide where to go into recursion and where not to
// also use the features
if self.nodes[current].n_type == Inner{
//cloneing is very expensiv and destroys the performance
self.nodes[current].children.as_ref().unwrap().clone().iter().for_each(|&n| self.calc_h(n, features));
self.do_smt(current)
}
self.do_smt(current)
}
}
编辑:
- Lagerbaer 建议使用 as_mut 但这会导致 current 成为 &mut 使用大小,这并不能真正解决问题。
- 把孩子变成了孩子
解决方案
child 的正确复数形式是children,所以这就是我将在此答案中提及的内容。大概这就是childs
您的代码中的含义。
由于node.children
已经是Option
,因此最好的解决方案是.take()
在迭代开始时将向量从节点中取出并在最后放入。这样我们就避免了tree.nodes
在迭代期间持有对的引用。
if self.nodes[current].n_type == Inner {
let children = self.nodes[current].children.take().unwrap();
for &child in children.iter() {
self.calc_h(child, features);
}
self.nodes[current].children = Some(children);
}
请注意,在循环的情况下,行为与原始代码不同,但如果树的其余部分正确实现,则无需担心。
推荐阅读
- python - 如何在pygame中击中给定精灵后编写游戏计时器停止器?为什么我的计时器仍在运行,即使我仍在主菜单中?
- java - 在 hdfs 目录中创建文件时如何获得通知
- javascript - 使用依赖数组反应 useEffect 仍然循环
- julia - 如何在 CentOS7 上使用 wget 下载 julia 1.3.1?
- java - 将从 websocket 接收到的事件排入队列以进行异步处理的最佳方法
- python - 安装新软件包时如何修复pycharm环境错误
- java - 如何在运行时替换一个类?
- ios - 在 Swift Playgrounds 中使用 Reality Composer 项目文件
- isabelle - 非平凡列表函数的归纳
- ionic3 - 无法在离子中设置背景图像