首页 > 解决方案 > 在迭代器 inRust 上的嵌套循环

问题描述

在 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 用户如何仅使用迭代器来实现这一点——假设索引仅出于教育目的而无法实现。

标签: loopsrustnestediteratorborrow-checker

解决方案


我理解对数据进行通道写入访问的必要性,但我也想知道有经验的 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());
    }
}

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


推荐阅读