gpt4 book ai didi

struct - 如何将一个结构向量映射或转换为另一个结构向量?

转载 作者:行者123 更新时间:2023-12-03 11:49:20 25 4
gpt4 key购买 nike

最小的可复制示例

pub struct User {
pub id: i32,
pub name: String,
pub match_id: i32,
}

pub struct Match {
pub id: i32,
pub name: String,
}

pub struct MatchWithUsers {
pub id: i32,
pub name: String,
pub users: Vec<User>,
}

fn main() {
let query_result: Vec<(Match, Option<User>)> = vec![
(
Match {
id: 1,
name: String::from("1st match"),
},
Some(User {
id: 1,
name: String::from("Jack"),
match_id: 1,
}),
),
(
Match {
id: 2,
name: String::from("2nd match"),
},
Some(User {
id: 2,
name: String::from("John"),
match_id: 2,
}),
),
(
Match {
id: 3,
name: String::from("3rd match"),
},
None,
),
];
let mut response: Vec<MatchWithUsers> = Vec::new();

for (m, u) in &query_result {
let existing_match = &response
.into_iter()
.find(|match_with_user| match_with_user.id == m.id);

match existing_match {
Some(found_match) => {
println!("Inser user into match: {}", found_match.name);
match u {
Some(mut user) => {
found_match.users.push(user);
}
None => println!("No users."),
}
}
None => {
println!("No existing match. Add to response.");
let user = u.as_ref().unwrap();
response.push(MatchWithUsers {
id: m.id,
name: m.name.clone(),
users: vec![],
});
}
}
}

println!("Response with: {}", response.len());
}

warning: unused variable: `user`
--> src/main.rs:69:21
|
69 | let user = u.as_ref().unwrap();
| ^^^^ help: consider prefixing with an underscore: `_user`
|
= note: `#[warn(unused_variables)]` on by default

warning: variable does not need to be mutable
--> src/main.rs:61:26
|
61 | Some(mut user) => {
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default

error[E0382]: use of moved value: `response`
--> src/main.rs:53:31
|
50 | let mut response: Vec<MatchWithUsers> = Vec::new();
| ------------ move occurs because `response` has type `std::vec::Vec<MatchWithUsers>`, which does not implement the `Copy` trait
...
53 | let existing_match = &response
| ^^^^^^^^ value moved here, in previous iteration of loop

error[E0507]: cannot move out of `u.0` which is behind a shared reference
--> src/main.rs:60:23
|
60 | match u {
| ^
61 | Some(mut user) => {
| --------
| |
| data moved here
| move occurs because `user` has type `User`, which does not implement the `Copy` trait

error[E0596]: cannot borrow `found_match.users` as mutable, as it is behind a `&` reference
--> src/main.rs:62:25
|
62 | found_match.users.push(user);
| ^^^^^^^^^^^^^^^^^ `found_match` is a `&` reference, so the data it refers to cannot be borrowed as mutable

Playground

我的问题

我有 an API test project using Rocket and Diesel

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

我的解决方案尝试
  • 我创建了一个向量。
  • 迭代查询结果;
  • 检查匹配是否已经存在于我的向量中,如果存在,则添加用户信息(来自查询结果)并将其添加到当前MatchWithUser的users属性中,否则只需向向量添加一个结构体(MatchWithUsers)。
  • pub fn show_all_matches2() -> Vec<MatchWithUsers> {
    use schema::*;

    let connection = establish_connection();

    let query_result: Vec<(Match, Option<User>)> = matches::table
    .left_join(users::table.on(users::match_id.eq(matches::id)))
    .load(&connection)
    .expect("Error loading matches");

    let mut response: Vec<MatchWithUsers> = Vec::new();

    for (m, u) in &query_result {
    let existing_match = &response
    .into_iter()
    .find(|match_with_user| match_with_user.id == m.id);

    match existing_match {
    Some(mut found_match) => {
    println!("Inser user into match: {}", found_match.name);
    found_match.users.push(u.unwrap());
    }
    None => {
    println!("No existing match. Add to response.");
    let user = u.as_ref().unwrap();
    response.push(MatchWithUsers {
    id: m.id,
    name: m.name.clone(),
    players_count: m.players_count,
    users: vec![User {
    id: user.id,
    name: user.name.clone(),
    match_id: user.match_id,
    }],
    });
    }
    }
    }

    response
    }

    结构
    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>,
    }

    失误

    $ cargo run
    Compiling got_board_api_v3 v0.1.0 (/Users/tauil/Projects/got/got-board-api-v3)
    error[E0382]: use of moved value: `response`
    --> src/lib.rs:54:31
    |
    51 | let mut response: Vec<MatchWithUsers> = Vec::new();
    | ------------ move occurs because `response` has type `std::vec::Vec<models::MatchWithUsers>`, which does not implement the `Copy` trait
    ...
    54 | let existing_match = &response
    | ^^^^^^^^ value moved here, in previous iteration of loop

    error[E0507]: cannot move out of `existing_match.0` which is behind a shared reference
    --> src/lib.rs:58:15
    |
    58 | match existing_match {
    | ^^^^^^^^^^^^^^
    59 | Some(mut found_match) => {
    | ---------------
    | |
    | data moved here
    | move occurs because `found_match` has type `models::MatchWithUsers`, which does not implement the `Copy` trait

    error[E0507]: cannot move out of `*u` which is behind a shared reference
    --> src/lib.rs:61:40
    |
    61 | found_match.users.push(u.unwrap());
    | ^
    | |
    | move occurs because `*u` has type `std::option::Option<models::User>`, which does not implement the `Copy` trait
    | help: consider borrowing the `Option`'s content: `u.as_ref()`

    在Postgres客户端中查询结果:

    select * from matches left join users on matches.id = users.match_id;

    id | name | players_count | id | name | match_id
    ----+---------------------+---------------+----+-----------+----------
    1 | My first match | 3 | 1 | Rafael | 1
    1 | My first match | 3 | 2 | Leandro | 1
    1 | My first match | 3 | 3 | Vagner | 1
    2 | Just a second match | 4 | 4 | Vagner | 2
    2 | Just a second match | 4 | 5 | Leandro | 2
    2 | Just a second match | 4 | 6 | Rafael | 2
    2 | Just a second match | 4 | 7 | Wanderson | 2
    3 | Amazing match | 6 | | |
    (8 rows)

    最佳答案

    如果您从group_by crate 中使用 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();

    Playground

    关于struct - 如何将一个结构向量映射或转换为另一个结构向量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60764099/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com