在 Rust 中迭代、过滤和映射数据从一个结构体到另一个结构体

问题描述

结构

pub struct UserAccess {
    pub user: String,pub dept: String,pub hreflink: String,}

pub struct RoleMembers {
    pub role: String,pub members: Vec<String>,}


pub struct DepartmentAccess {
    pub department: String,pub department_id: String,pub role_members: Vec<RoleMembers>,}

我正在尝试根据来自 UI 的输入(“用户”和“部门”)过滤 DepartmentAccess 结构中的数据,并且需要将“用户”、“部门 ID”和“参考链接”映射到UI 所需的另一个结构 (UserAccess)。但是在构建它时会抛出如下错误。我需要在这里做什么?

代码

  let mut v: Vec<UserAccess> = vec![];
    let access_data = get_access_data();
    let user_data: Vec<UserAccess> = access_data
        .into_iter()
        .filter(|a| a.department == department && a.role_members.iter().any(|b| b.members.contains(&user)))
        .map(|r| {
            v.push(UserAccess {
                user: user,dept: r.department_id,hreflink: format!("department/{}",r.department_id),})
        })
        .collect();

错误

value of type `Vec<UserAccess>` cannot be built from `std::iter::Iterator<Item=()>`
   |
   = help: the trait `FromIterator<()>` is not implemented for `Vec<UserAccess>`

解决方法

错误似乎很清楚。

collect() 创建迭代器返回的任何内容的集合。但这里你的地图回调:

    |r| {
        v.push(UserAccess {
            user: user,dept: r.department_id,hreflink: format!("department/{}",r.department_id),})
    }

返回 whatever Vec::push returns,即 ()(也就是没有,不要与不返回混淆)。

这与您请求的 Vec<UserAccess> 完全不兼容。

为什么你们既要填充一个 vec,又要尝试从同一处理管道中同时使用相同的数据收集到一个 vec?

选择一个:

  • 要么从回调中返回 UserData 并收集到 user_data
  • 或者针对其副作用执行管道并通过突变填充 v,在这种情况下,我会推荐 for_each 或常规 for 循环以“泵送”迭代器-- 迭代器是惰性的,所以 map 本身不会运行任何东西 -- 并且表明最后一步是有副作用的:map 通常用于执行函数转换,至少主要看重他们的结果。并且 collect 不是运行迭代器直至完成的正确方法。