我试图做一个功能,将做到以下几点:
输入:一个String形式的任意长度的"ABC/DEF/GHI"
输出:一个String所有以"/"反转分离子; 在这个例子中,输出将是"cba/fed/ihg".
不仅仅是函数本身,我关心变异函数生成的迭代器背后的一般原理split().
以下是我的最大努力:
fn reverse_string(input: &mut str) -> String {
input
.to_string()
.split('/')
.map(move |x| x.to_string().rev())
.collect::<String>()
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨说
error[E0599]: no method named `rev` found for type `std::string::String` in the current scope
--> src/main.rs:5:37
|
5 | .map(move |x| x.to_string().rev())
| ^^^
|
= note: the method `rev` exists but the following trait bounds were not satisfied:
`&mut std::string::String : std::iter::Iterator`
`&mut str : std::iter::Iterator`
Run Code Online (Sandbox Code Playgroud)
这意味着什么,我该如何解决这个问题?
如果您正在学习迭代器,我建议您在实际执行之前首先决定您想要做什么。
例如,以下是单个内存分配的示例:
fn reverse_string(input: &str) -> String {
let mut result = String::with_capacity(input.len());
for portion in input.split('/') {
if !result.is_empty() {
result.push('/');
}
for c in portion.chars().rev() {
result.push(c);
}
}
result
}
Run Code Online (Sandbox Code Playgroud)
迭代器通常专注于不修改其环境的纯方法。不幸的是,这可能会导致效率低下,因为这意味着String向左和向右创建和删除。
现在,从技术上讲,您可以改变环境map(需要一个FnMut),但它只是不受欢迎,因为按照惯例,读者希望它是纯粹的。
因此,当您想要引入额外的状态时,Iterator::fold首选方法是:
fn reverse_string(input: &str) -> String {
input
.split('/')
.fold(
String::with_capacity(input.len()),
|mut acc, portion| {
if !acc.is_empty() {
acc.push('/');
}
for c in portion.chars().rev() {
acc.push(c);
}
acc
}
)
}
Run Code Online (Sandbox Code Playgroud)
第一个参数是一个累加器,它被传递给闭包的每次调用,然后返回它。最后,在调用结束时fold,返回累加器。
无论是在逻辑上还是在效率上,这都相当于第一个函数,但说实话,我更喜欢这个for版本。