Running a number of consecutive replacements on the same string

前端 未结 3 332
盖世英雄少女心
盖世英雄少女心 2021-01-12 08:43

I found this example for substring replacement:

use std::str;
let string = \"orange\";
let new_string = str::replace(string, \"or\", \"str\");
3条回答
  •  攒了一身酷
    2021-01-12 09:42

    how would you write multiple chained substring replacements?

    I would do it just as asked:

    fn main() {
        let a = "hello";
        let b = a.replace("e", "a").replace("ll", "r").replace("o", "d");
        println!("{}", b);
    }
    

    It you are asking how to do multiple concurrent replacements, passing through the string just once, then it does indeed get much harder.

    This does require allocating new memory for each replace call, even if no replacement was needed. An alternate implementation of replace might return a Cow which only includes the owned variant when the replacement would occur. A hacky implementation of that could look like:

    use std::borrow::Cow;
    
    trait MaybeReplaceExt<'a> {
        fn maybe_replace(self, needle: &str, replacement: &str) -> Cow<'a, str>;
    }
    
    impl<'a> MaybeReplaceExt<'a> for &'a str {
        fn maybe_replace(self, needle: &str, replacement: &str) -> Cow<'a, str> {
            // Assumes that searching twice is better than unconditionally allocating
            if self.contains(needle) {
                self.replace(needle, replacement).into()
            } else {
                self.into()
            }
        }
    }
    
    impl<'a> MaybeReplaceExt<'a> for Cow<'a, str> {
        fn maybe_replace(self, needle: &str, replacement: &str) -> Cow<'a, str> {
            // Assumes that searching twice is better than unconditionally allocating
            if self.contains(needle) {
                self.replace(needle, replacement).into()
            } else {
                self
            }
        }
    }
    
    fn main() {
        let a = "hello";
        let b = a.maybe_replace("e", "a")
            .maybe_replace("ll", "r")
            .maybe_replace("o", "d");
        println!("{}", b);
    
        let a = "hello";
        let b = a.maybe_replace("nope", "not here")
            .maybe_replace("still no", "i swear")
            .maybe_replace("but no", "allocation");
        println!("{}", b);
        assert_eq!(b.as_ptr(), a.as_ptr());
    }
    

提交回复
热议问题