我找到了这个替换子字符串的例子:
use std::str;
let string = "orange";
let new_string = str::replace(string, "or", "str");
如果我想在同一个字符串上运行多个连续替换,为了清理目的,如何在不为每次替换分配新变量的情况下执行此操作?
如果您要编写惯用的Rust,您将如何编写多个链式子串替换?
答案 0 :(得分:4)
你会如何编写多个链式子串替换?
我会按照要求这样做:
fn main() {
let a = "hello";
let b = a.replace("e", "a").replace("ll", "r").replace("o", "d");
println!("{}", b);
}
你问的是如何做多个并发替换,只通过一次字符串,然后它确实让多更难。
这确实需要为每个replace
呼叫分配新内存,即使不需要替换也是如此。 replace
的替代实现可能返回Cow<str>
,其仅在替换发生时包含所拥有的变体。一个hacky实现可能看起来像:
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());
}
答案 1 :(得分:3)
标准库中没有办法做到这一点;根据许多因素,对于如何做到这一点,要做出大量变化是一件非常棘手的事情。您需要自己编写这样的函数。
答案 2 :(得分:3)
regex engine可以用来做多次替换字符串的单次传递,但如果这实际上更高效,我会感到惊讶:
extern crate regex;
use regex::{Captures, Regex};
fn main() {
let re = Regex::new("(or|e)").unwrap();
let string = "orange";
let result = re.replace_all(string, |cap: &Captures| {
match &cap[0] {
"or" => "str",
"e" => "er",
_ => panic!("We should never get here"),
}.to_string()
});
println!("{}", result);
}