我遇到了一个典型的借用检查器错误,我希望人们可以向我展示一些惯用的解决方案。下面请看一个微型示例。
#[derive(Debug)]
pub struct Cell {
ploidy: u32,
}
impl Cell {
fn from_ploidy(ploidy: u32) -> Self {
Cell { ploidy }
}
fn hybrid(&mut self, cell: Cell) { // I would like `cell` to be consumed.
self.ploidy += cell.ploidy;
}
}
fn main() {
let mut cells = vec![
Cell::from_ploidy(46), Cell::from_ploidy(40),
Cell::from_ploidy(46), Cell::from_ploidy(40)
];
println!("{:?}", cells);
// To hybrid every two consecutive cells
// e.g. cells[0].hybrid(cells[1]);
// cells[2].hybrid(cells[3]);
// and let go cells[1] and cells[3]
for i in 0..2usize {
cells[i*2].hybrid(cells[i*2+1]);
}
println!("{:?}", cells);
}
错误是
cannot borrow `cells` as immutable because it is also borrowed as mutable
immutable borrow occurs here
基本上我希望将
cells[1]
、cells[3]
的资源移至cells[0]
、cells[2]
,同时将cells[1]
、cells[3]
本身从cells
中释放。
如果您使用
Vec
并且合并的单元格不一定相邻,那么您会遇到一些麻烦。您不能直接从任何索引中提取值,因为 Vec
s 的元素必须始终是连续的。无论是移动元素的补救措施还是使用 swap_remove
从末尾填充,您都会遇到索引对不再稳定的问题。
不用担心,有很多方法可以按照我们喜欢的方式订购东西。理想的情况是对单元格进行排序,使得被消耗的单元格位于末尾,而相应的单元格被合并到开头,这样
cells[idx]
就可以与 cells.pop()
中的单元格合并(因此位于最前面的单元格)结尾应该是相反的顺序)。
我们可以使用我的答案中的代码来创建此排序如何按索引对 Vec 进行排序(重新排序)?并像这样创建排序顺序:
let mut cells = vec![
Cell::from_ploidy(0), Cell::from_ploidy(1),
Cell::from_ploidy(2), Cell::from_ploidy(3),
Cell::from_ploidy(4), Cell::from_ploidy(5),
];
let pairs = vec![(1, 5), (0, 3), (4, 2)];
let sort_indicies = Iterator::chain(
pairs.iter().map(|(a, _)| *a),
pairs.iter().map(|(_, b)| *b).rev(),
).collect();
sort_by_indices(&mut cells, sort_indicies);
然后只需按照我上面概述的步骤合并单元格即可:
for i in 0..cells.len()/2 {
let cell_to_merge = cells.pop().unwrap();
cells[i].hybrid(cell_to_merge);
}
我们就完成了!完整的代码和演示输出可在playground获得。您将看到它输出合并的单元格,如
pairs
: 所述
merging 1 with 5
merging 0 with 3
merging 4 with 2
我有一个由 n 个单元组成的向量,其中我随机挑选 k 对(当然,没有重采样),然后对于每一对,将后者融合到前者中,并最终释放后者
如果这应该随机完成,那么我们不需要跟踪我们想要合并的确切对,我们只需打乱数组并只执行最后一步!
use rand::thread_rng;
use rand::seq::SliceRandom;
cells.shuffle(&mut thread_rng());
for i in 0..cells.len()/2 {
let cell_to_merge = cells.pop().unwrap();
cells[i].hybrid(cell_to_merge);
}
再次在操场上提供了演示,并且示例输出如下所示合并:
merging 5 with 0
merging 3 with 4
merging 2 with 1