rust Vec〈Vec< ...>>在子向量之间移动项

busg9geu  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(185)

拥有

let mut stacks = vec![
    vec!['A', 'B'], 
    vec!['C', 'D', 'E', 'F'],
];

println!("vec: {:?}", stacks);

哪个打印

vec: [['A', 'B'], ['C', 'D', 'E', 'F']]

我想把'E'和'F'从第二个向量移到第一个向量,结果是:

vec: [['A', 'B', 'E', 'F'], ['C', 'D']]

我能做到这一点的唯一方法是使用临时辅助向量:

let col_from = 1;
let col_to = 0;
let n_to_move = 2;

let len = stacks[col_from].len();

let crates = stacks[col_from].drain(len - n_to_move..);

let mut temp = Vec::new();
temp.extend(crates);

stacks[col_to].extend(temp);

println!("vec: {:?}", stacks);

这是可行的,但我想知道是否有更简洁的方法来实现这一点。

ibps3vxo

ibps3vxo1#

假设你的问题是你试图同时获取两个对stacks的可变引用,这样你就可以改变两个元素。类似这样:

stacks[col_to].extend(stacks[col_from].drain(stacks[col_from].len() - n_to_move..));

这是不允许使用索引的,因为如果索引是相同的,那么你将有两个对同一数据的可变引用,编译器不能静态地检查这一点。
相反,你可以使用slice::split_at_mut,它提供了两个可变的(不重叠的)切片,然后你可以从这些切片中得到你需要的部分。
代码可能如下所示:

// This won't work if the columns are the same, but it also wouldn't make sense as an operation
assert!(col_from != col_to);

let (src, dest) = if col_from < col_to {
    let (a, b) = stacks.split_at_mut(col_to);
    (&mut a[col_from], &mut b[0])
} else {
    let (a, b) = stacks.split_at_mut(col_from);
    (&mut b[0], &mut a[col_to])
};
dest.extend(src.drain(src.len() - n_to_move..));

很难说这比您的代码“更简洁”,但它至少避免了复制任何数据或新的分配。

相关问题