rust 如何在检查其他元素的同时习惯性地迭代可变向量

tkclm6bt  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(106)

我想这样写代码:

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();
  }
}

这不起作用,因为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();
  }
}

在铁 rust 中做这件事的惯用方法是什么?

xxb16uws

xxb16uws1#

在处理此类问题时,您必须考虑是否可以将 * 读取 * 与 * 写入 * 分开。因此,我们需要挑选e.val变化将触发count总变化的地方,并将其拆分。碰巧的是,只有当some_predicate()true切换到false时,我们才可以按如下方式rewrite the code

let mut v: Vec<Object> = Vec::new();
let mut count = v.iter().filter(|o| o.some_predicate()).count();

for e in &mut v {
  if e.some_predicate() {
    e.val = count;
    if !e.some_predicate() {
      count -= 1;
    }
  }
}

我不能说这个解决方案是惯用的,因为每个问题都是独特的。但我们有几个速度改进。现在我们不必计算 predicate N²次。以及载体的存取也变得线性化。我们不使用索引,所以没有额外的边界检查。

相关问题