我写了以下代码:
use std::str::{from_utf8};
struct JSONPointer {
segments: Vec<String>
}
fn build_json_pointer(s: Vec<String>) -> JSONPointer {
JSONPointer { segments: s.iter().map(|x| x.replace("~1", "/").replace("~0", "~")).collect() }
}
fn main() {
let v = vec!["foo".to_string(), "bar".to_string(), "baz~1".to_string()];
let p = build_json_pointer(v);
println!("Hello world! {:?}", p.segments);
}
这一切都适用于String
,但理想情况下我的JSONPointer
结构将包含Vec<&str>
(如果仅用于学习目的)。我遇到的问题发生在map
的调用中,取代了一些保留的字符串。无论我使用的转换组合如何,我总是被告知我的borrowed value does not live long enough
。
我理解我正在引用本地值并尝试返回它(导致可能的删除后使用错误),但我似乎无法找到一种方法来获取副本字符串。
编辑:已更新为最低可重复格式
我现在意识到,当我指的是想要一个&#34;副本&#34; (堆分配),这正是String
的内容。尽管如此,还是谈到了一种更清洁的方式。
答案 0 :(得分:3)
如果您担心不必要地分配字符串,可以使用Cow
:
use std::borrow::Cow;
struct JSONPointer<'a> {
segments: Vec<Cow<'a, str>>,
}
fn replace_if<'a>(s: Cow<'a, str>, from: &str, to: &str) -> Cow<'a, str> {
if s.contains(from) {
Cow::Owned(s.replace(from, to))
} else {
s
}
}
fn build_json_pointer<'a>(s: &[&'a str]) -> JSONPointer<'a> {
let segments = s.iter().cloned()
.map(Cow::Borrowed)
.map(|x| replace_if(x, "~1", "/"))
.map(|x| replace_if(x, "~0", "~"))
.collect();
JSONPointer { segments: segments }
}
fn main() {
let v = vec!["foo", "bar", "baz~1"];
let p = build_json_pointer(&v);
println!("Hello world! {:?}", p.segments);
}
这样做的好处是,当不需要替换时,它不需要分配任何内存,但缺点是每个模式都要被搜索两次。使用像rope这样的结构可能会更有效率。
对于接受String
的原始案例,您可以通过保留原始Cow
而不是无条件地替换原来的String
来实现类似的内容:
struct JSONPointer {
segments: Vec<String>,
}
fn replace_if(s: String, from: &str, to: &str) -> String {
if s.contains(from) {
s.replace(from, to)
} else {
s
}
}
fn build_json_pointer(s: &[String]) -> JSONPointer {
let segments = s.iter().cloned()
.map(|x| replace_if(x, "~1", "/"))
.map(|x| replace_if(x, "~0", "~"))
.collect();
JSONPointer { segments: segments }
}
fn main() {
let v = vec!["foo".to_string(), "bar".to_string(), "baz~1".to_string()];
let p = build_json_pointer(&v);
println!("Hello world! {:?}", p.segments);
}