【发布时间】:2020-06-30 23:55:13
【问题描述】:
最小可重现示例
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
我的问题
我有an API test project using Rocket and Diesel。
以下方法执行 Diesel 查询并将结果映射到 JSON 响应。这是数据库中所有与他们的用户匹配的响应。用户应该嵌套在每个Match 节点中。
我的解决方案尝试
- 我创建了一个向量。
- 在查询结果中迭代;
- 检查匹配是否已经存在于我的向量中,如果存在,添加用户信息(来自查询结果)并将其添加到当前
MatchWithUser中的用户属性中,否则只需添加一个结构(@987654335 @) 到向量。
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)
【问题讨论】:
-
您应该考虑使用
HashMap<i32, MatchWithUsers>而不是Vec,这在查找重复项时效率更高,然后使用EntryAPI 插入或修改存储的值。 -
@Jmb 感谢您的反馈和回答。我已经用错误文本更新了问题。我也会尝试一下HashMap。我已经看到了一些例子,但我实际上与我最初想做的有点不同。
-
看来Does Rust have a way to apply a function/method to each element in an array or vector? 的答案可能会回答您的问题。如果没有,请edit您的问题解释差异。否则,我们可以将此问题标记为已回答。
-
很难回答您的问题,因为它不包含minimal reproducible example,强调minimal。如果您尝试在Rust Playground 上重现您的错误,如果可能的话,这将使我们更容易为您提供帮助,否则在全新的 Cargo 项目中,然后在edit 您的问题中包含附加信息。您可以使用Rust-specific MRE tips 来减少您在此处发布的原始代码。谢谢!
-
请将错误粘贴为问题中的文本,而不是图像。这样以后遇到同样问题的其他人就可以搜索到它。