【问题标题】:How to find and replace every matching slice of bytes with another slice?如何用另一个切片查找和替换每个匹配的字节切片?
【发布时间】:2019-06-06 14:26:48
【问题描述】:

我有一个字节向量,想用[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]);

【问题讨论】:

  • 替换切片的长度是否必须与要替换的切片长度相同?或者您可能需要缩小/扩大Vec
  • 我认为目前&[u8] 上没有任何方便的通用例程可以为您执行此操作,类似于str::replace 方法。我可能只是自己实现它,可能通过复制implementation for str::replace。 (我正在为 Rust 开发一个字节字符串库,它肯定会支持这样的操作。但它还没有完成。)
  • 在此处应用链接的问题建议buf[0..3].copy_from_slice(&[4, 5, 6]);。如果切片大小不同,则可能是 Efficiently insert or replace multiple elements in the middle or at the beginning of a Vec? 的副本
  • 我的错误,我忽略了问题中的“每个”一词。但是上面的链接还是很好看的。

标签: replace rust slice


【解决方案1】:

这个功能可以完成这项工作:

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

Playground


示例 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]);
}

Playground

【讨论】:

    【解决方案2】:

    这适用于切片具有不同长度的情况(类似于 replace for str):

    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
    }
    

    【讨论】:

      【解决方案3】:

      没有递归:

      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() 以跳过不必要的检查。
      • @ÖmerErden source.len() - from.len() 会在 from 大于 source 时出现恐慌。
      • @trentcl 感谢您的指出,由于“starts_with”中的断言,当“from”和“to”的大小不相等时,它也会出现恐慌。在循环之前添加警卫会有所帮助。
      • @ÖmerErden starts_with 如果selfneedle 的大小不同,则不会惊慌;它只是返回false
      • @trentcl 抱歉应该是“clone_from_slice”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多