I found this example for substring replacement:
use std::str;
let string = \"orange\";
let new_string = str::replace(string, \"or\", \"str\");
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
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());
}