我想写这样的代码:
let mut v: Vec<Object> = Vec::new();
for e in v.iter_mut() {
if e.some_predicate() {
e.val = v.iter().filter(|o| o.some_predicate()).count();
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为 for 循环接受可变借用,然后iter尝试进行不可变借用。我理解为什么借用检查器不喜欢生成的特定类型,但是我尝试执行的操作似乎是安全的,如果我将其重写为使用索引,它可以正常工作:
let mut v: Vec<Object> = Vec::new();
for i in 0..v.len() {
if v[i].some_predicate() {
v[i].val = v.iter().filter(|o| o.some_predicate()).count();
}
}
Run Code Online (Sandbox Code Playgroud)
在 Rust 中这样做的惯用方法是什么?
在处理此类问题时,您必须考虑是否可以将读取和写入分开。e.val因此,我们需要找出变化会触发总体变化的地方count并将其拆分。事实上,只有当some_predicate()从 切换true到时,false我们才可以将代码重写如下:
let mut v: Vec<Object> = Vec::new();\nlet mut count = v.iter().filter(|o| o.some_predicate()).count();\n\nfor e in &mut v {\n if e.some_predicate() {\n e.val = count;\n if !e.some_predicate() {\n count -= 1;\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n我不能说这个解决方案是惯用的,因为每个问题都是独特的。但我们已经取得了一些速度方面的改进。现在我们不必计算谓词 N\xc2\xb2 次。并且向量的访问也变得线性。我们不使用索引,因此没有额外的边界检查。
\n