如何修改集合同时迭代它? [英] How can I modify a collection while also iterating over it?
问题描述
我有一个 Board
(又名& mut Vec< Vec< Cell>>
)喜欢迭代它时更新。我想要更新的新值来自一个函数,该函数需要& Vec< Vec< Cell>>
到我正在更新的集合。
I have a Board
(a.k.a. &mut Vec<Vec<Cell>>
) which I would like to update while iterating over it. The new value I want to update with is derived from a function which requires a &Vec<Vec<Cell>>
to the collection I'm updating.
我尝试了几件事:
-
使用
board.iter_mut()。enumerate()
和row.iter_mut()。enumerate()
以便我可以更新最内层循环中的
。 Rust不允许调用 | next_gen
函数,因为它需要& Vec< Vec< Cell>>
并且你当你已经有一个可变引用时,不能有一个不可变引用。
Use
board.iter_mut().enumerate()
androw.iter_mut().enumerate()
so that I could update thecell
in the innermost loop. Rust does not allow calling thenext_gen
function because it requires a&Vec<Vec<Cell>>
and you cannot have a immutable reference when you already have a mutable reference.
将 next_gen
函数签名更改为接受& mut Vec< Vec< Cell>>
。 Rust不允许对对象进行多次可变引用。
Change the next_gen
function signature to accept a &mut Vec<Vec<Cell>>
. Rust does not allow multiple mutable references to an object.
我目前正在将所有更新推迟到 HashMap
然后在我执行迭代后应用它们:
I'm currently deferring all the updates to a HashMap
and then applying them after I've performed my iteration:
fn step(board: &mut Board) {
let mut cells_to_update: HashMap<(usize, usize), Cell> = HashMap::new();
for (row_index, row) in board.iter().enumerate() {
for (column_index, cell) in row.iter().enumerate() {
let cell_next = next_gen((row_index, column_index), &board);
if *cell != cell_next {
cells_to_update.insert((row_index, column_index), cell_next);
}
}
}
println!("To Update: {:?}", cells_to_update);
for ((row_index, column_index), cell) in cells_to_update {
board[row_index][column_index] = cell;
}
}
有没有办法让我可以使这个代码更新 board
就地,也就是说,在最里面的循环中,同时仍然可以调用 next_gen
在最里面的循环内?
Is there a way that I could make this code update the board
"in place", that is, inside the innermost loop while still being able to call next_gen
inside the innermost loop?
免责声明:
我正在学习Rust和我知道这不是最好的方法。我正在玩,看看我能做什么,不能做什么。我也试图限制任何复制以限制自己一点点。正如 oli_obk - ker提到的那样,Conway的生命游戏的这种实现存在缺陷。
I'm learning Rust and I know this is not the best way to do this. I'm playing around to see what I can and cannot do. I'm also trying to limit any copying to restrict myself a little bit. As oli_obk - ker mentions, this implementation for Conway's Game of Life is flawed.
此代码旨在衡量一些事项:
This code was intended to gauge a couple of things:
- 如果这是可能的话
- 如果它是惯用的Rust
从我收集到的内容注释,可以使用 std :: cell :: Cell
。但是,使用 std:cell:Cell
规避了一些核心Rust原则,我在原始问题中将其描述为两难。
From what I have gathered in the comments, it is possible with std::cell::Cell
. However, using std:cell:Cell
circumvents some of the core Rust principles, which I described as my "dilemma" in the original question.
推荐答案
有没有办法让这个代码就地更新电路板?
Is there a way that I could make this code update the board "in place"?
存在专门为这些情况制作的类型。巧合的是,它名为 std :: cell :: Cell
。你被允许改变 Cell
的内容,即使它已被多次不可挽回地借用。 Cell
仅限于实现复制
的类型(对于您必须使用的其他人 RefCell
,如果涉及多个线程然后你必须使用 Arc
与 互斥
)。
There exists a type specially made for situations such as these. It's coincidentally called std::cell::Cell
. You're allowed to mutate the contents of a Cell
even when it has been immutably borrowed multiple times. Cell
is limited to types that implement Copy
(for others you have to use RefCell
, and if multiple threads are involved then you must use an Arc
in combination with somethinng like a Mutex
).
use std::cell::Cell;
fn main() {
let board = vec![Cell::new(0), Cell::new(1), Cell::new(2)];
for a in board.iter() {
for b in board.iter() {
a.set(a.get() + b.get());
}
}
println!("{:?}", board);
}
这篇关于如何修改集合同时迭代它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!