How to find and replace every matching slice of bytes with another slice?

rust vec
string byte slice

I have a byte vector and want to replace every [1, 2, 3] with [4, 5, 6]. How is this possible in Rust?

let mut buf = vec![1, 2, 3, 7, 8];

// ?

assert_eq!(buf, vec![4, 5, 6, 7, 8]);

This function can do the job:

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

This function is recursive but you can rewrite it using loops as well.


Example 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


Example 2: (From the comment by 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

How to replace all the elements in slice of bytes in Golang , In the Go slice of bytes, you are allowed to replace all the elements in the given slice using the If the given old slice is empty, then it matches at the start of the slice and after each UTF-8 Check out this Author's contributed articles. See your article appearing on the GeeksforGeeks main page and help other Geeks. func Replace(s, old, new []byte, n int) []byte. Replace returns a copy of the slice s with the first n non-overlapping instances of old replaced by new. If old is empty, it matches at the beginning of the slice and after each UTF-8 sequence, yielding up to k+1 replacements for a k-rune slice. If n < 0, there is no limit on the number of replacements.

Without recursion:

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

Programming in Go: Creating Applications for the 21st Century, Regexp; s is the string to match; b is the []byte to match; r is the io. A nil return means no match(es). Syntax rx.Expand() rx.ExpandString() rx.Find(b) rx. Description/result Performs the $ replacements done by the Replace- All() matches or nil An [][]int (a slice of 2-item slices) each identifying a match or nil;e.g.​,  String is immutable byte sequence. Byte slice is mutable byte sequence. Rune slice is re-grouping of byte slice so that each index is a character. String is a nice way to deal with short sequence, of bytes or characters. Everytime you operate on string, such as find replace string or take substring, a new string is created.

This works when the slices have different lengths (similar to 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
}

PC Mag, How SLICE Keeps Track: A 30-byte Section File [Header WEVE com LOT TO BACK US UP Each of these sections has the same filename as the original file, but carries an This field through FNAME is returned by the DOS Find File function. If the information does not match, the program requests another diskette. A slice List example string example tuple example. There is another way than slice object for slicing in Python i.e. the extended slicing. It uses the colons syntax i.e. object[start:stop:step] Where object can be a list, string, tuple etc. Extended slice example. This way is explained in the later part of this tutorial, so keep reading.

std::str::from_utf8, A string slice ( &str ) is made of bytes ( u8 ), and a byte slice ( &[u8] ) is made of bytes, so this function converts between the two. Not all byte slices are valid string  Python string method replace() returns a copy of the string in which the occurrences of old have been replaced with new, optionally restricting the number of replacements to max. Syntax Following is the syntax for replace() method −

std::string::String, Converts a slice of bytes to a string, including invalid characters. During this conversion, from_utf8_lossy() will replace any invalid UTF-8 sequences This function is unsafe because it does not check that the bytes passed to it are valid UTF-8. Remember, char s may not match your human intuition about characters:. The slice() function returns a slice object. In this tutorial, we will learn to use Python slice() function in detail with the help of examples.

Golang: String, Byte Slice, Rune Slice, Rune slice is re-grouping of byte slice so that each index is a character. Everytime you operate on string, such as find replace string or take  In addition to being able to replace a value with another string value, we can also use Regular Expressions to make replace() more powerful. For instance, replace() only affects the first value, but we can use the g (global) flag to catch all instances of a value, and the i (case insensitive) flag to ignore case.

Comments
  • Is the replacement slice necessarily the same length as the slice to replace? Or might you have to shrink/grow the Vec?
  • I don't think there is any convenient general routine defined on &[u8] currently that does this for you, similar to the str::replace method. I'd probably just implement it myself, possibly by copying the implementation for str::replace. (I am working on a byte string library for Rust, which will certainly support operations like this. But it's not finished yet.)
  • Possible duplicate of How to idiomatically copy a slice?
  • Applying the linked question here suggests buf[0..3].copy_from_slice(&[4, 5, 6]);. If the slices are not the same size, it's probably a duplicate of Efficiently insert or replace multiple elements in the middle or at the beginning of a Vec? instead
  • My mistake, I overlooked the word "every" in the question. But the links above are still good to look at.
  • You may consider to change your loop into this : for i in 0..=buf.len() - from.len() to skip unnecessary checks.
  • @ÖmerErden source.len() - from.len() will panic when from is larger than source.
  • @trentcl thanks for pointing it out, it will also panic when "from" and "to" are not equally sized, due to assertion in "starts_with". Adding guards before loop will help.
  • @ÖmerErden starts_with doesn't panic if self and needle are different sizes; it just returns false.
  • @trentcl sorry it should be "clone_from_slice"