如何过滤文件路径然后使用生成的路径

How to filter file paths then use the resulting paths

我试图从目录中获取 mp3 列表。

let dir_paths = fs::read_dir(&Path::new("some_directory")).unwrap();

let paths = dir_paths.filter(|x| match x.unwrap().path().extension() {
    None => true,
    Some(ext) => ext == "mp3"
});

错误信息

src/main.rs:27:48: 27:49 error: cannot move out of borrowed content
src/main.rs:27     let paths = dir_paths.filter(|ref x| match x.unwrap().path().extension() {
                                                              ^

我尝试用 |ref x| 替换 |x| 但得到了相同的错误消息。这样做的正确方法是什么

我们来看看Result::unwrap的文档:

fn unwrap(self) -> T

Unwraps a result, yielding the content of an Ok.

请注意 self 需要多少时间?这意味着该选项将被消耗。但是,您的迭代器将闭包传递给 &Result<T, _>。您不能取得 Option 的所有权,因为它是借来的。

最短的解决方法是使用 as_ref:

来获得 Result<&T, _>
use std::fs;

fn main() {
    let dir_paths = fs::read_dir("/").unwrap();

    let paths = dir_paths.filter(|x| match x.as_ref().unwrap().path().extension() {
        None => true,
        Some(ext) => ext == "mp3"
    });
}

虽然我可能会选择写成

use std::fs;
use std::ffi::OsStr;

fn main() {
    let dir_paths = fs::read_dir("/").unwrap();

    dir_paths
        .filter_map(|x| x.ok())
        .filter(|x| x.path().extension().and_then(OsStr::to_str) == Some("mp3"));
}

有一些较少的展开 - 我们只是忽略任何失败的 DirEntrys。不过,这取决于您的错误处理策略。