如何 flat_map 并从字符串的迭代器中拆分
How to flat_map and split from an iterator of Strings
有没有办法在不切换到使用 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
时,我得到了一个引用迭代器并且一切正常,但我想知道是否可以在 [=17] 的迭代器上进行这项工作=]s.
您的代码的问题在于您正在执行这些操作:
- 您正在使用
into_iter
使用您的向量
- 因此,在闭包内部,您通过
split
借用了 String
的值
- 在您的临时迭代器中,您持有对此字符串的引用
结论:您正在尝试 return 对局部变量的引用。
要解决此问题,您必须从拆分字符串创建拥有的字符串,并收集它们以不再保留引用:
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<_>>());
}
我遇到了同样的问题,最终创建了一个迭代器来获取字符串的所有权,这是代码。由于您按 space 拆分,它应该适合
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)
}
有没有办法在不切换到使用 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
时,我得到了一个引用迭代器并且一切正常,但我想知道是否可以在 [=17] 的迭代器上进行这项工作=]s.
您的代码的问题在于您正在执行这些操作:
- 您正在使用
into_iter
使用您的向量
- 因此,在闭包内部,您通过
split
借用了 - 在您的临时迭代器中,您持有对此字符串的引用
String
的值
结论:您正在尝试 return 对局部变量的引用。
要解决此问题,您必须从拆分字符串创建拥有的字符串,并收集它们以不再保留引用:
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<_>>());
}
我遇到了同样的问题,最终创建了一个迭代器来获取字符串的所有权,这是代码。由于您按 space 拆分,它应该适合
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)
}