免责声明:Rust我还很陌生。
从到目前为止我所了解的关于Rust的最佳实践中,我了解到for elem in array {}
的迭代比for i in 0..array.len(){}
的迭代更受欢迎。
有什么方法可以可变地遍历数组,同时通过索引从数组中访问特定元素?
我的用例非常复杂,因此我编写了一个简单的斐波那契计算器来演示该问题:
let mut arr = vec![0;10];
arr[0] = 1;
arr[1] = 1;
for (i, elem) in arr.iter_mut().skip(2).enumerate() {
*elem = arr[i-2] + arr[i-1];
}
println!("{:?}", arr);
错误[E0502]:无法借用
arr
作为不可变的,因为它也借来了可变的
这当然是有道理的,但是有办法解决吗?我的意思是,从程序员的角度来看,这段代码显然是安全的,因为我们从当前上下文中已经可变的数组中借用了不可变的变量,而不是直接地,而是通过迭代器。
当然,如果我通过遍历索引来实现它,那么它将起作用:
let mut arr = vec![0;10];
arr[0] = 1;
arr[1] = 1;
for i in 2..arr.len(){
arr[i] = arr[i-2] + arr[i-1];
}
println!("{:?}", arr);
[1、2、3、5、8、13、21、34、55]
所以,我的问题是,有没有其他方法可以解决此问题,还是我必须使用第二个版本?
此代码是为了演示我的用例,而不是单独执行任何操作。
let mut labels = vec![vec![0; width]; height];
for (y, row) in labels.iter_mut().enumerate() {
for (x, label) in row.iter_mut().enumerate() {
let label_left = {
if x > 0 && some_condition() {
Some(labels[y][x - 1]) // <== Fails
} else {
None
}
};
let label_top = {
if y > 0 && some_condition() {
Some(labels[y - 1][x]) // <== Fails
} else {
None
}
};
*label = some_function(label_left, label_right);
}
}
使用基于2D索引的迭代来重写它很像我试图将C编程风格强制引入Rust,所以我不敢相信这是预期的方式。
答案 0 :(得分:1)
一种更“实用”的方式来实现您的简化用例可以是:
fn main() {
let mut arr = vec![0; 10];
arr[0] = 1;
arr[1] = 1;
let arr: Vec<i32> = arr
.iter()
.skip(2)
.scan((arr[0], arr[1]), |pair, _| {
let (a, b) = *pair;
let c = a + b;
*pair = (b, c);
Some(c)
})
.collect();
println!("{:?}", arr);
}
但是,与索引迭代相比,这不一定更生锈或更容易阅读。就是说,如果您愿意沿着FP兔子洞走下去,那将是非常有益的。