我编写了以下代码:
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。
据我所知,我引用了一个本地值,并试图返回它(导致一个可能的使用后删除错误),但我似乎找不到一种方法来获取字符串的副本。
编辑:更新为最小可复制形式
现在我意识到,当我指的是想要一个“副本”(堆分配的)时,这正是String。有人说要用一种更干净的方法来做这件事,尽管如此。
发布于 2016-05-21 00:41:38
如果您担心不必要地分配字符串,则有可能使用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()
.copied()
.map(Cow::Borrowed)
.map(|x| replace_if(x, "~1", "/"))
.map(|x| replace_if(x, "~0", "~"))
.collect();
JSONPointer { segments }
}
fn main() {
let v = vec!["foo", "bar", "baz~1"];
let p = build_json_pointer(&v);
println!("Hello world! {:?}", p.segments);
}这样做的好处是,当不需要进行替换时,它不需要分配任何内存,但是缺点是每个模式都被搜索了两次。如果使用像绳这样的结构,它可能会更高效。
对于接受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 }
}
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);
}https://stackoverflow.com/questions/37356131
复制相似问题