我有这个函数:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.into_iter()
.map(|x| x.map(|entry| entry.path()))
.collect()
}它实际上是从here借来的。这个函数还可以;不幸的是,我并不真正理解它是如何工作的。
Ok(["/home/ey/dir-src/9", "/home/ey/dir-src/11", "/home/ey/dir-src/03 A Letter of Explanation.mp3", "/home/ey/dir-src/02 Egyptian Avenue.mp3", "/home/ey/dir-src/alfa", "/home/ey/dir-src/10"])测试输出会同时显示目录和文件,这是理所应当的。我不知道该把文件/目录的过滤放在哪里。我不明白为什么映射中的映射:它不只是一个简单的路径列表吗?这个表达式中到底发生了什么?
更新:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.into_iter()
.map(|x| x.map(|entry| entry.path()))
.filter(|x| {x.as_ref().map(|entry| entry); true})
.collect()
}插入了一个普通的过滤器(总是true)。它至少正在编译,但我仍然不知道如何使用entry进行文件/目录检查。对不起:)
发布于 2019-09-23 21:01:30
让我们一步一步地走完这条链。
fs::read_dir(dir)?创建目录的读句柄,如果发生则立即传播Err事件,如果没有,则unwraps成功(即?操作符)
.into_iter()将此读句柄转换为Result<DirEntry>的迭代器
.map(|x|
x.map(|entry| entry.path())
)如果结果是实际的DirEntry,则在迭代器的每个元素上调用path()方法。因为迭代器元素是Result<DirEntry>而不仅仅是DirEntry,所以第二个map()允许您干净利落地处理这个问题。剩下的路径就是在输出中看到的路径
.collect()将此迭代器转换回由类型提示定义的结构(这里是一个向量)
过滤部分可以在调用map()之前或之后实现,以将条目转换为PathBuf。如果您需要根据元素本身而不是PathBuf进行过滤,请在它之前进行过滤。如果您可以根据PathBuf进行过滤,请根据它进行过滤。
filter()组合器函数的使用很简单--你给它一个闭包,它会把它应用到每个元素上。如果闭包的返回值为true,则保留该元素。如果为false,则删除该元素。
下面是一个仅返回目录的示例:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
Ok(fs::read_dir(dir)?
.into_iter()
.filter(|r| r.is_ok()) // Get rid of Err variants for Result<DirEntry>
.map(|r| r.unwrap().path()) // This is safe, since we only have the Ok variants
.filter(|r| r.is_dir()) // Filter out non-folders
.collect())
}发布于 2021-06-12 00:25:44
您可以合并2个filter调用并保留来自read_dir的结果。deref将能够检查路径是否为dir,而不使用结果。
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.map(|r| r.map(|d| d.path()))
.filter(|r| r.is_ok() && r.as_deref().unwrap().is_dir())
.collect()
}您还可以将过滤器和映射与filter_map结合使用,并使用ok().and_then()取消解包。
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
Ok(fs::read_dir(dir)?
.filter_map(|e| {
e.ok().and_then(|d| {
let p = d.path();
if p.is_dir() {
Some(p)
} else {
None
}
})
})
.collect())
}https://stackoverflow.com/questions/58062887
复制相似问题