有没有一种方法可以在不切换到使用iter
而不是into_iter
的情况下实现这一点?
let strings: Vec<String> = vec!["1 2".to_string(), "3 4".to_string()];
strings.into_iter().flat_map(|str| str.split(" "));
问题是
error[E0515]: cannot return value referencing function parameter `str`
--> src/lib.rs:3:40
|
3 | strings.into_iter().flat_map(|str| str.split(" "));
| ---^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `str` is borrowed here
当使用iter
而不是into_iter
时,我得到了一个引用的迭代器,一切都正常,但我想知道是否可以在String
s的迭代机上实现。
代码的问题在于您正在执行以下操作:
- 您正在使用
into_iter
消耗矢量 - 因此,在闭包中,您通过使用
split
借用的值来获取String
- 在临时迭代器中,您持有对以下字符串的引用
结论:您正试图返回对局部变量的引用。
为了解决这个问题,您必须从拆分的字符串中创建所拥有的字符串,并收集它们以不再包含引用:
fn main() {
let strings = vec!["1 2".to_string(), "3 4".into()];
let result = strings.into_iter().flat_map(|str| str.split(" ").map(str::to_owned).collect::<Vec<_>>());
println!("{:?}", result.collect::<Vec<_>>());
}
事实上,如果一开始不消耗矢量,成本会更低:
fn main() {
let strings = vec!["1 2".to_string(), "3 4".into()];
let result = strings.iter().flat_map(|str| str.split(" ")).map(str::to_owned);
println!("{:?}", result.collect::<Vec<_>>());
}
我遇到了同样的问题,最终创建了一个迭代器来获得字符串的所有权,下面是代码。既然你是按空间划分的,它应该适合
struct Words {
buf: String,
offset: usize,
}
impl Words {
fn new(buf: String) -> Words {
Words { buf, offset: 0 }
}
}
impl Iterator for Words {
type Item = String;
fn next(&mut self) -> Option<String> {
let s = &(self.buf)[self.offset..];
let left = s.chars().take_while(|x| x.is_whitespace()).count();
let right = left + s[left..].chars().take_while(|x| !x.is_whitespace()).count();
if left < right {
self.offset += right;
return Some(String::from(&s[left..right]));
}
None
}
}
以下是我如何使用
fn read_file<'a>(buf: impl BufRead) -> impl Iterator<Item = String> {
buf.lines().filter_map(Result::ok).flat_map(Words::new)
}