我如何将下面的代码打包到一个迭代器中?
use std::io::{BufRead, BufReader};
use std::fs::File;
let file = BufReader::new(File::open("sample.txt").expect("Unable to open file"));
for line in file.lines() {
for ch in line.expect("Unable to read line").chars() {
println!("Character: {}", ch);
}
}
天真地说,我希望有这样的东西(我跳过了解开)
let lines = file.lines().next();
Reader {
line: lines,
char: next().chars()
}
并迭代Reader.char
,直到None
,然后刷新Reader.line
到新的一行,刷新Reader.char
到该行的第一个字符,但这似乎是不可能的,因为Reader.char
依赖于临时变量。
请注意,这个问题是关于嵌套迭代器的,阅读文本文件只是一个例子。
1条答案
按热度按时间iszxjhcz1#
可以使用
flat_map()
迭代器实用程序创建新的迭代器,该迭代器可以为它所调用的迭代器中的每个项生成任意数量的项。在本例中,由于
lines()
返回Result
s的迭代器,所以Err
的情况必须处理。还有一个问题,
.chars()
引用原始字符串以避免额外的分配,因此必须将字符收集到另一个可迭代容器中。解决这两个问题会导致这种混乱:
如果
String
给了我们一个into_chars()
方法,我们可以在这里避免使用collect()
,但是这样我们就有了不同类型的迭代器,并且需要使用Box<dyn Iterator>
或者类似either::Either
的方法。因为这里已经使用了
.expect()
,所以可以通过在闭包中使用.expect()
来避免处理Err
的情况,从而稍微简化一些:在一般情况下,
flat_map()
通常很简单,你只需要注意你是在迭代自有值还是借入值;这两种情况都有一些尖角,在这种情况下,迭代拥有的String
值会使使用.chars()
出现问题,如果我们可以迭代借用的str
切片,我们就不必使用.collect()
。