我期待有一种Vec::insert_slice(index, slice)
方法— String::insert_str()
确实存在字符串()的解决方案。
我知道Vec::insert()
,但是一次只插入一个元素,而不是切片。或者,当前置切片为一个切片时,Vec
可以附加一个切片,但这不能一概而论。惯用的解决方案可能使用Vec::splice()
,但如示例中那样使用迭代器会让我抓狂。
其次,似乎从文档中排除了前置的整个概念。没有任何提及。我会很感激关于原因的评论。注意,Vec::swap_remove()
确实存在相对模糊的方法。
我的典型用例由索引字节字符串组成。
String::insert_str
利用字符串本质上是一个Vec<u8>
. 它重新分配底层缓冲区,将所有初始字节移动到末尾,然后将新字节添加到开头。
这通常是不安全的,不能直接添加,Vec
因为在复制过程中Vec
它不再处于有效状态——数据中有“漏洞”。
这无关紧要,String
因为数据是u8
和u8
不实现Drop
. 有一个任意没有这样的保证T
的Vec
,但如果你是非常仔细地跟踪您的状态,并妥善清理,你可以做同样的事情-这是什么splice
呢!
整个前置的概念似乎已被驱除
我想这是因为Vec
从性能的角度来看,在 a 之前是一个糟糕的主意。如果你需要这样做,天真的情况很简单:
fn prepend<T>(v: Vec<T>, s: &[T]) -> Vec<T>
where
T: Clone,
{
let mut tmp: Vec<_> = s.to_owned();
tmp.extend(v);
tmp
}
Run Code Online (Sandbox Code Playgroud)
这具有更高的内存使用量,因为我们需要有足够的空间用于v
.
该splice
方法接受新值的迭代器和要替换的值范围。在这种情况下,我们不想替换任何内容,因此我们给出了要插入的索引的空范围。我们还需要将切片转换为适当类型的迭代器:
let s = &[1, 2, 3];
let mut v = vec![4, 5];
v.splice(0..0, s.iter().cloned());
Run Code Online (Sandbox Code Playgroud)
splice
的实现是不平凡的,但它有效地完成了我们需要的跟踪。删除一大块值后,它会为新值重用那块内存。它还会移动向量的尾部(可能会移动几次,具体取决于输入迭代器)。的Drop
实现Slice
确保事物始终处于有效状态。
我更惊讶的是VecDeque
不支持它,因为它旨在更有效地修改数据的头部和尾部。
归档时间: |
|
查看次数: |
2518 次 |
最近记录: |