Struct 如何将一个结构向量映射或转换为另一个结构向量? 最小可重复示例 pub结构用户{ 酒吧id:i32, 酒吧名称:String, pub match_id:i32, } 发布结构匹配{ 酒吧id:i32, 酒吧名称:String, } pub结构与用户匹配{ 酒吧id:i32, 酒吧名称:String, 酒吧用户:Vec, } fn main(){ 让我们查询结果:Vec=Vec[ ( 匹配{ id:1, 名称:String::from(“第一个匹配”), }, 一些(用户){ id:1, 名称:String::from(“Jack”), 匹配id:1, }), ), ( 匹配{ id:2, 名称:String::from(“第二个匹配”), }, 一些(用户){ id:2, 名称:String::from(“John”), 匹配id:2, }), ), ( 匹配{ id:3, 名称:String::from(“第三匹配”), }, 没有一个 ), ]; 让mut响应:Vec=Vec::new(); 对于(m,u)输入查询结果(&u){ 让现有的_匹配=&响应 .into_iter() .find(| match_with_user | match_with_user.id==m.id); 匹配现有的\u匹配{ 一些(找到匹配项)=>{ println!(“将用户插入匹配项:{}”,找到了\u match.name); 匹配你{ 一些(多用户)=>{ 找到匹配的.users.push(用户); } 无=>println!(“无用户”), } } 无=>{ println!(“没有现有匹配项。添加到响应。”); 让user=u.as_ref().unwrap(); 响应。推送(与用户匹配){ id:m.id, 名称:m.name.clone(), 用户:vec![], }); } } } println!(“带有:{}的响应,Response.len()); } 警告:未使用的变量:`user` -->src/main.rs:69:21 | 69 |让用户=u.作为|参考().展开(); ^ ^ ^ ^帮助:考虑前缀与下划线:“用户” | =注意:`#[警告(未使用的_变量)]`默认打开 警告:变量不需要是可变的 -->src/main.rs:61:26 | 61 |一些(多用户)=>{ | ----^^^^ | | |帮助:删除此“mut”` | =注意:`#[warn(unused_mut)]`默认打开 错误[E0382]:使用移动值:`response` -->src/main.rs:53:31 | 50 |让mut响应:Vec=Vec::new(); |-----发生移动是因为`response`的类型为`std::vec::vec`,而该类型未实现`Copy`特性 ... 53 |让现有的_匹配=&响应 |^^^^^^^^^值在循环的上一次迭代中移动到此处 错误[E0507]:无法移出共享引用后面的'u.0' -->src/main.rs:60:23 | 60 |匹配u{ | ^ 61 |一些(多用户)=>{ | -------- | | |数据移到这里 |发生移动是因为'user'的类型为'user',而该类型不实现'Copy'特性 错误[E0596]:无法将'found_match.users'作为可变项借用,因为它位于`&`引用后面 -->src/main.rs:62:25 | 62 |找到|匹配.用户.推送(用户); |^^^^^^^^^^^^^^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^

Struct 如何将一个结构向量映射或转换为另一个结构向量? 最小可重复示例 pub结构用户{ 酒吧id:i32, 酒吧名称:String, pub match_id:i32, } 发布结构匹配{ 酒吧id:i32, 酒吧名称:String, } pub结构与用户匹配{ 酒吧id:i32, 酒吧名称:String, 酒吧用户:Vec, } fn main(){ 让我们查询结果:Vec=Vec[ ( 匹配{ id:1, 名称:String::from(“第一个匹配”), }, 一些(用户){ id:1, 名称:String::from(“Jack”), 匹配id:1, }), ), ( 匹配{ id:2, 名称:String::from(“第二个匹配”), }, 一些(用户){ id:2, 名称:String::from(“John”), 匹配id:2, }), ), ( 匹配{ id:3, 名称:String::from(“第三匹配”), }, 没有一个 ), ]; 让mut响应:Vec=Vec::new(); 对于(m,u)输入查询结果(&u){ 让现有的_匹配=&响应 .into_iter() .find(| match_with_user | match_with_user.id==m.id); 匹配现有的\u匹配{ 一些(找到匹配项)=>{ println!(“将用户插入匹配项:{}”,找到了\u match.name); 匹配你{ 一些(多用户)=>{ 找到匹配的.users.push(用户); } 无=>println!(“无用户”), } } 无=>{ println!(“没有现有匹配项。添加到响应。”); 让user=u.as_ref().unwrap(); 响应。推送(与用户匹配){ id:m.id, 名称:m.name.clone(), 用户:vec![], }); } } } println!(“带有:{}的响应,Response.len()); } 警告:未使用的变量:`user` -->src/main.rs:69:21 | 69 |让用户=u.作为|参考().展开(); ^ ^ ^ ^帮助:考虑前缀与下划线:“用户” | =注意:`#[警告(未使用的_变量)]`默认打开 警告:变量不需要是可变的 -->src/main.rs:61:26 | 61 |一些(多用户)=>{ | ----^^^^ | | |帮助:删除此“mut”` | =注意:`#[warn(unused_mut)]`默认打开 错误[E0382]:使用移动值:`response` -->src/main.rs:53:31 | 50 |让mut响应:Vec=Vec::new(); |-----发生移动是因为`response`的类型为`std::vec::vec`,而该类型未实现`Copy`特性 ... 53 |让现有的_匹配=&响应 |^^^^^^^^^值在循环的上一次迭代中移动到此处 错误[E0507]:无法移出共享引用后面的'u.0' -->src/main.rs:60:23 | 60 |匹配u{ | ^ 61 |一些(多用户)=>{ | -------- | | |数据移到这里 |发生移动是因为'user'的类型为'user',而该类型不实现'Copy'特性 错误[E0596]:无法将'found_match.users'作为可变项借用,因为它位于`&`引用后面 -->src/main.rs:62:25 | 62 |找到|匹配.用户.推送(用户); |^^^^^^^^^^^^^^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^,struct,rust,Struct,Rust,我的问题 我有 以下方法执行Diesel查询,并应将结果映射到JSON响应。这是数据库中所有匹配用户的响应。用户应嵌套在每个Match节点中 我的解决方案尝试 我创建一个向量 迭代查询结果 检查匹配是否已存在于my vector中,如果已存在,请添加用户信息(来自查询结果)并将其添加到当前MatchWithUser中的users属性中,否则只需向向量添加一个结构(MatchWithUsers) 如果从itertools板条箱中使用,并且确保查询结果按匹配ID排序,则可以非常轻松地获得与每个匹配相

我的问题 我有

以下方法执行Diesel查询,并应将结果映射到JSON响应。这是数据库中所有匹配用户的响应。用户应嵌套在每个
Match
节点中

我的解决方案尝试
  • 我创建一个向量
  • 迭代查询结果
  • 检查匹配是否已存在于my vector中,如果已存在,请添加用户信息(来自查询结果)并将其添加到当前
    MatchWithUser
    中的users属性中,否则只需向向量添加一个结构(
    MatchWithUsers

  • 如果从
    itertools
    板条箱中使用,并且确保查询结果按匹配ID排序,则可以非常轻松地获得与每个匹配相关联的用户的匹配列表:

    use itertools::Itertools; // 0.9.0
    let response: Vec<_> = query_result
        .into_iter()
        // Note that this assumes that `query_result` is sorted
        // by match id since `group_by` only considers
        // consecutive matches.
        .group_by(|(m, _)| m.id)
        .into_iter()
        .map(|(id, mut g)| {
            // Now `g` is an iterator of `(Match, Option<User>)`
            // where all the matches are the same. We take the
            // first item to get the match information. Note
            // that it is safe to unwrap here because `group_by`
            // would never call us with an empty `g`.
            let (m, u) = g.next().unwrap();
            MatchWithUsers {
                id: id,
                name: m.name,
                // We got the first user along with the match
                // information, now we append the other users
                // from the remaining items in `g`.
                users: u
                    .into_iter()
                    .chain(g.flat_map(|(_, u)| u.into_iter()))
                    .collect(),
            }
        })
        .collect();
    
    使用itertools::itertools;//0.9.0
    let response:Vec=查询结果
    .into_iter()
    //请注意,这假定“查询结果”已排序
    //按匹配id,因为“group_by”只考虑
    //连续的比赛。
    .group|by(|(m,|)m.id)
    .into_iter()
    .map(|(id,mut g)|{
    //现在'g'是`(匹配,选项)的迭代器`
    //所有的比赛都是一样的,我们拿
    //获取匹配信息的第一项。注意
    //在这里拆开是安全的,因为“分组”`
    //永远不会用空的“g”称呼我们。
    设(m,u)=g.next().unwrap();
    与用户匹配{
    id:id,
    姓名:m.name,
    //我们在比赛中得到了第一个用户
    //信息,现在我们附加其他用户
    //从“g”中的剩余项中。
    用户:u
    .into_iter()
    .chain(g.flat_映射(|(|,u)| u.到_iter())
    .collect(),
    }
    })
    .收集();
    

    而不是<代码> VEC<代码>,你应该考虑使用<代码> HashMap <代码>,这将在寻找重复的时候更有效,然后使用API来插入或修改存储的值。@ JMB感谢反馈和回答。我已经用错误文本更新了问题。我也会给HashMap一个尝试。我见过一些EX。我很喜欢,但我觉得有点不一样
    use crate::schema::{matches, users};
    use serde::{Deserialize, Serialize};
    
    #[derive(Queryable, Identifiable, Associations, Serialize, Deserialize)]
    #[belongs_to(Match)]
    #[table_name = "users"]
    pub struct User {
        pub id: i32,
        pub name: String,
        pub match_id: i32,
    }
    
    #[derive(Queryable, Identifiable, Serialize, Deserialize)]
    #[table_name = "matches"]
    pub struct Match {
        pub id: i32,
        pub name: String,
        pub players_count: i32,
    }
    
    #[derive(Serialize, Deserialize)]
    pub struct MatchWithUsers {
        pub id: i32,
        pub name: String,
        pub players_count: i32,
        pub users: Vec<User>,
    }
    
    use itertools::Itertools; // 0.9.0
    let response: Vec<_> = query_result
        .into_iter()
        // Note that this assumes that `query_result` is sorted
        // by match id since `group_by` only considers
        // consecutive matches.
        .group_by(|(m, _)| m.id)
        .into_iter()
        .map(|(id, mut g)| {
            // Now `g` is an iterator of `(Match, Option<User>)`
            // where all the matches are the same. We take the
            // first item to get the match information. Note
            // that it is safe to unwrap here because `group_by`
            // would never call us with an empty `g`.
            let (m, u) = g.next().unwrap();
            MatchWithUsers {
                id: id,
                name: m.name,
                // We got the first user along with the match
                // information, now we append the other users
                // from the remaining items in `g`.
                users: u
                    .into_iter()
                    .chain(g.flat_map(|(_, u)| u.into_iter()))
                    .collect(),
            }
        })
        .collect();