我有一个字节向量,想要用[4, 5, 6]
替换每个[1, 2, 3]
。在Rust中如何实现?
let mut buf = vec![1, 2, 3, 7, 8];
// ?
assert_eq!(buf, vec![4, 5, 6, 7, 8]);
当切片的长度不同时,此方法有效(类似于str
的replace
方法):
fn replace<T>(source: &[T], from: &[T], to: &[T]) -> Vec<T>
where
T: Clone + PartialEq
{
let mut result = source.to_vec();
let from_len = from.len();
let to_len = to.len();
let mut i = 0;
while i + from_len <= result.len() {
if result[i..].starts_with(from) {
result.splice(i..i + from_len, to.iter().cloned());
i += to_len;
} else {
i += 1;
}
}
result
}
fn replace_slice<T>(source: &mut [T], from: &[T], to: &[T])
where
T: Clone + PartialEq,
{
let iteration = if source.starts_with(from) {
source[..from.len()].clone_from_slice(to);
from.len()
} else {
1
};
if source.len() > from.len() {
replace_slice(&mut source[iteration..], from, to);
}
}
示例1:
fn main() {
let mut buf = vec![1, 2, 3, 7, 8, 1, 2, 3];
replace_slice(&mut buf[..], &[1, 2, 3], &[4, 5, 6]);
assert_eq!(buf, vec![4, 5, 6, 7, 8, 4, 5, 6]);
}
示例2: (来自评论者trentcl)
fn main() {
let mut buf = vec![1, 2, 3, 3, 4, 1, 2, 3];
replace_slice(&mut buf[..], &[1, 2, 3], &[5, 1, 2]);
assert_eq!(buf, vec![5, 1, 2, 3, 4, 5, 1, 2]);
}
不使用递归:
fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T])
where
T: Clone + PartialEq,
{
for i in 0..=buf.len() - from.len() {
if buf[i..].starts_with(from) {
buf[i..(i + from.len())].clone_from_slice(to);
}
}
}
for i in 0..=buf.len() - from.len()
,以跳过不必要的检查。 - Ömer Erdenfrom
大于 source
时,source.len() - from.len()
将会引发 panic。 - trent
Vec
吗? - trent&[u8]
上,可以像str::replace
方法一样为您完成此操作。我可能会自己实现它,可能通过复制str::replace
的实现方式来实现(https://doc.rust-lang.org/src/alloc/str.rs.html#268-278)。 (我正在为Rust编写一个字节字符串库,肯定会支持此类操作。但它还没有完成。) - BurntSushi5buf[0..3].copy_from_slice(&[4, 5, 6]);
。如果切片大小不同,则可能是 Efficiently insert or replace multiple elements in the middle or at the beginning of a Vec? 的重复。 - trent[1,2,3,3]
中用[5,1,2]
取代[1,2,3]
,你希望得到的结果是[5,1,2,3]
吗?两个现有的答案都会给你[5,5,1,2]
。 - trent