【问题标题】:Nested loops over an iterator inRustRust 中迭代器上的嵌套循环
【发布时间】:2021-05-18 19:22:50
【问题描述】:

在 C 中,我可以使用索引以嵌套方式对数组进行可变迭代。在 Rust 中,我几乎可以使用索引来做同样的事情,但是如果我想使用迭代器而不是索引呢?

以下代码示例编译成功,因为两个借用都是不可变的:

let xs = [0, 1, 2];
for x in &xs {
    for y in &xs {
        println!("x={} y={}", *x, *y);
    }
}

但是如果我想使用可变迭代器呢?

let mut xs = [0, 1, 2];
for x in &mut xs {
    *x += 1;
    for y in &mut xs {
        *y += 1;
        println!("x={} y={}", *x, *y);
    }
}

这会导致:

error[E0499]: cannot borrow `xs` as mutable more than once at a time

我了解对数据进行通道写入访问的必要性,但我也想知道经验丰富的 Rust 用户如何仅使用迭代器来实现这一点——假设索引仅用于教育目的。

【问题讨论】:

  • while let 可用于此目的,正如this thread 中指出的那样
  • This article 深入解决了这个问题。
  • 没有办法用迭代器做到这一点,因为有时xy 指向xs 中的同一个项目,并被用来改变这个项目。除了使用您排除的索引之外,唯一的解决方法是将xs 更改为Cells 的向量以限制可变访问的范围。

标签: loops rust nested iterator borrow-checker


【解决方案1】:

我了解对数据进行通道写入访问的必要性,但我也想知道经验丰富的 Rust 用户如何仅使用迭代器来实现这一点

他们不会,因为它不可行,至少不是原样:虽然去糖到 while let 是一种常用方法,但它适用于您想要推进的嵌套循环相同的迭代器 在外循环和内循环中,它避免了跨整个循环的排他借用。

不过,您不想在不同的地方推进同一个迭代器,而是希望将两个不同的变异迭代器推进到同一个集合。这意味着您对同一个集合有两个不同的可变引用(这是不允许的),并且您最终会对集合的同一项目有两个可变引用(这也是不允许的)。

充其量,您可以使用内部可变性来解决问题,例如

let xs = [Cell::new(0), Cell::new(1), Cell::new(2)];
for x in &xs {
    x.set(x.get() + 1);
    for y in &xs {
        y.set(y.get() + 1);
        println!("x={} y={}", x.get(), y.get());
    }
}

但我认为这不是通常的选择(退回到索引会是,因为它不需要更改数据本身)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多