You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何更简洁地在嵌套Vec间移动指定元素?

Rust 向量元素批量移动优化方案

问题背景

初始代码:

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

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

运行输出:

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

需求:将第二个子Vec末尾的'E'和'F'移动到第一个子Vec中,预期输出:

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

现有实现依赖临时Vec:

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); 

需要更简洁或无需临时向量的实现方式。

优化实现方案

方案一:直接消费Drain迭代器

drain方法返回的Drain迭代器可以直接被extend接收,完全不需要临时Vec中转:

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

let len = stacks[col_from].len();
// 直接用drain的结果扩展目标向量,省去临时内存分配
stacks[col_to].extend(stacks[col_from].drain(len - n_to_move..));

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

这段代码逻辑和原实现一致,但去掉了不必要的临时Vec,代码更紧凑,效率也更高——extend会直接迭代Drain产生的元素,没有额外的内存拷贝。

方案二:使用split_off拆分向量

如果要移动的刚好是原向量末尾的所有目标元素,split_off是更高效的选择:

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

let len = stacks[col_from].len();
// split_off会把从指定索引到末尾的元素拆分出来,原向量仅保留前半部分
let moved_elements = stacks[col_from].split_off(len - n_to_move);
stacks[col_to].extend(moved_elements);

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

split_off是Vec的内置方法,它通过调整内部的指针和长度实现拆分,不会复制元素,性能最优,代码也更直观。

方案三:Unsafe手动内存操作(仅性能敏感场景)

如果追求极致性能,可通过unsafe代码直接操作Vec的底层内存,但这种方式复杂度高,容易引入内存安全问题,非必要不建议使用:

use std::mem;

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

let from_stack = &mut stacks[col_from];
let to_stack = &mut stacks[col_to];

let from_len = from_stack.len();
let start_idx = from_len - n_to_move;

unsafe {
    // 预分配目标向量的内存空间
    to_stack.reserve(n_to_move);
    // 移动元素到目标向量末尾
    let src_ptr = from_stack.as_mut_ptr().add(start_idx);
    let dst_ptr = to_stack.as_mut_ptr().add(to_stack.len());
    mem::copy_nonoverlapping(src_ptr, dst_ptr, n_to_move);
    // 更新两个向量的长度
    to_stack.set_len(to_stack.len() + n_to_move);
    from_stack.set_len(start_idx);
}

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

使用这段代码需要确保所有指针操作的安全性,比如源和目标内存无重叠、指针有效等。

内容的提问来源于stack exchange,提问作者tmaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:23:09