You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust:如何合并迭代逻辑,创建Struct并收集为Result<Vec<MyStruct>,MyError>?

合并WalkDir迭代与自定义类型转换的Rust实现

原代码示例

假设你原本的代码结构如下(包含walker和rewalk函数):

use walkdir::{DirEntry, WalkDir, Error as WalkDirError};
use std::error::Error;

#[derive(Debug)]
struct MyStruct {
    path: String,
    is_file: bool,
}

#[derive(Debug)]
enum MyError {
    WalkDir(WalkDirError),
    Conversion(String),
}

impl From<WalkDirError> for MyError {
    fn from(e: WalkDirError) -> Self {
        MyError::WalkDir(e)
    }
}

// 遍历目录并收集符合条件的DirEntry
fn walker(path: &str) -> Result<Vec<DirEntry>, WalkDirError> {
    WalkDir::new(path)
        .into_iter()
        .filter_map(|entry| entry.ok())
        .filter(|entry| entry.file_type().is_file())
        .collect()
}

// 转换DirEntry为MyStruct
fn rewalk(entries: Vec<DirEntry>) -> Result<Vec<MyStruct>, MyError> {
    let mut result = Vec::new();
    for entry in entries {
        let path = entry.path().to_str()
            .ok_or_else(|| MyError::Conversion("Invalid UTF-8 path".to_string()))?
            .to_string();
        let is_file = entry.file_type().is_file();
        result.push(MyStruct { path, is_file });
    }
    Ok(result)
}

重构后的合并实现

通过迭代器链式调用,直接在遍历过程中完成筛选和类型转换,最终返回Result<Vec<MyStruct>, MyError>:

use walkdir::{DirEntry, WalkDir, Error as WalkDirError};
use std::error::Error;

#[derive(Debug)]
struct MyStruct {
    path: String,
    is_file: bool,
}

#[derive(Debug)]
enum MyError {
    WalkDir(WalkDirError),
    Conversion(String),
}

impl From<WalkDirError> for MyError {
    fn from(e: WalkDirError) -> Self {
        MyError::WalkDir(e)
    }
}

// 合并遍历与转换逻辑的函数
fn walk_and_convert(path: &str) -> Result<Vec<MyStruct>, MyError> {
    WalkDir::new(path)
        .into_iter()
        // 将WalkDir的错误转换为自定义MyError
        .map(|entry| entry.map_err(MyError::from))
        // 筛选符合条件的条目(示例:仅保留文件)
        .filter(|entry| {
            // 若条目是错误则保留,最终collect会返回该错误;若想跳过错误可改用filter_map
            entry.as_ref().map_or(true, |e| e.file_type().is_file())
        })
        // 将DirEntry转换为MyStruct,处理转换中的错误
        .map(|entry| {
            entry.and_then(|e| {
                let path = e.path().to_str()
                    .ok_or_else(|| MyError::Conversion("Invalid UTF-8 path".to_string()))?
                    .to_string();
                let is_file = e.file_type().is_file();
                Ok(MyStruct { path, is_file })
            })
        })
        // 自动收集为Result<Vec<MyStruct>, MyError>
        .collect()
}

fn main() -> Result<(), Box<dyn Error>> {
    let items = walk_and_convert("./")?;
    for item in items {
        println!("{:?}", item);
    }
    Ok(())
}

关键细节说明

  1. 错误类型兼容:通过From<WalkDirError> for MyError实现错误类型的自动转换,让WalkDir的遍历错误能无缝融入自定义错误体系。
  2. 迭代器链式处理:
    • map(|entry| entry.map_err(MyError::from)):将WalkDir返回的Result<DirEntry, WalkDirError>转为Result<DirEntry, MyError>。
    • filter:保留符合业务条件的条目,若遇到错误条目则保留(最终会终止迭代并返回错误);如果需要跳过错误而非返回,可替换为filter_map(|entry| entry.ok().filter(|e| e.file_type().is_file()))。
    • map(|entry| entry.and_then(...)):在每个成功的DirEntry上执行转换逻辑,同时处理转换过程中的异常(如路径非UTF-8)。
    • collect():Rust的迭代器collect方法支持自动将Result<T, E>序列收集为Result<Vec<T>, E>——一旦遇到第一个错误就终止迭代并返回该错误,否则返回所有成功转换的结果。

内容的提问来源于stack exchange,提问作者SomeNameUser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:20:04