遍历向量并将向量值推送到哈希映射中在 Rust 中?

huangapple go评论89阅读模式
英文:

Iterate over vector and push to a hashmap vector value in rust?

问题

我有一个用户向量,我想将它转换成一个哈希映射,其中键是用户的级别(一个字符串),值是用户的向量。

#[derive(Debug, Serialize, Deserialize)]
pub struct User {
    pub id: String,
    pub email: String,
    pub first_name: String,
    pub last_name: String,
    pub level: String,
}

let users: Vec<User> = serde_json::from_str(&data).unwrap();
let mut users_by_level: HashMap<String, Vec<User>> = HashMap::new();

for user in users.iter() {
    users_by_level
        .entry(user.level.clone())
        .or_insert(Vec::new())
        .push(user);
}

但我得到了这个错误 mismatched types expected 'User', found '&User'

有人可以帮我解决这个问题吗?我是 Rust 新手。

英文:

I have this vector of users and i want to transform it into hashmap with key as level of user (which is a string) and value as a vector of users

#[derive(Debug, Serialize, Deserialize)]
pub struct User {
    pub id: String,
    pub email: String,
    pub first_name: String,
    pub last_name: String,
    pub level: String,
}

let users: Vec&lt;User&gt; = serde_json::from_str(&amp;data).unwrap();
let mut users_by_level: HashMap&lt;String, Vec&lt;User&gt;&gt; = HashMap::new();

for user in users.iter() {
    users_by_level
        .entry(user.level.clone())
        .or_insert(Vec::new())
        .push(user);
}

But i'm getting this error mismatched types expected &#39;User&#39;, found &#39;&amp;User&#39;

Can anyone help me with this? i'm new to rust

答案1

得分: 3

iter 生成一个引用迭代器。如果您保留了Vec,这将非常有用,特别是因为您不需要克隆键。

let mut users_by_level: HashMap<&str, Vec<&User>> = HashMap::new();

for user in users.iter() {
    users_by_level
        .entry(&user.level)
        .or_insert(Vec::new())
        .push(user);
}

如果您想将所有权转移到HashMap,例如当您不需要Vec或者想要更改项目时,可以使用into_iter

let mut users_by_level: HashMap<String, Vec<User>> = HashMap::new();

for user in users.into_iter() {
    users_by_level
        .entry(user.level.clone())
        .or_insert(Vec::new())
        .push(user);
}

for循环会自动调用into_iter,因此您可以直接传递users以获得相同的效果。

for user in users {
英文:

iter produces an iterator of references. This is useful if you keep the Vec around, especially since you don't need to clone the key.

let mut users_by_level: HashMap&lt;&amp;str, Vec&lt;&amp;User&gt;&gt; = HashMap::new();

for user in users.iter() {
    users_by_level
        .entry(&amp;user.level)
        .or_insert(Vec::new())
        .push(user);
}

If you want to transfer ownership to the HashMap, like when you don't need the Vec or you want to mutate the items, you can use into_iter.

let mut users_by_level: HashMap&lt;String, Vec&lt;User&gt;&gt; = HashMap::new();

for user in users.into_iter() {
    users_by_level
        .entry(user.level.clone())
        .or_insert(Vec::new())
        .push(user);
}

For loops call into_iter automatically, so you can simply pass users directly to get the same thing.

for user in users {

答案2

得分: 0

给你报错类型不匹配的原因是,当你遍历一个像 Vec 这样的集合时,你会得到一个对集合内部数据的引用。在这种情况下,由于你正在遍历用户向量,for 循环中的单个条目是类型为 User 的借用 &User,因此在将其插入到 HashMap 中时,你应该尝试克隆正在迭代的用户,像这样:

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct User {
    pub id: String,
    pub email: String,
    pub first_name: String,
    pub last_name: String,
    pub level: String,
}

fn main() {
    let users: Vec<User> = serde_json::from_str(&data).unwrap();
    let mut users_by_level: HashMap<String, Vec<User>> = HashMap::new();

    for user in users.iter() {
        users_by_level
            .entry(user.level.clone())
            .or_insert(Vec::new())
            .push(user.clone());
    }
}

用户结构体可以派生克隆特质,因为它由可克隆的类型组成(在这种情况下是拥有的字符串)。然后在 for 循环中,当你将用户作为值插入时,你使用 .clone() 方法将用户复制到可变的 HashMap 中。

英文:

The reason why its giving you a mismatch type error is that when you are iteration through a collection like a Vec, you are given a borrow to the data within the collection. In this case since you are iterating through the users vector, the individual entry within the for loop is a borrow of type User &amp;User, therefore you should attempt to clone the user that is being iterated when you insert it within the HashHap, like so:

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct User {
    pub id: String,
    pub email: String,
    pub first_name: String,
    pub last_name: String,
    pub level: String,
}

fn main() {
    let users: Vec&lt;User&gt; = serde_json::from_str(&amp;data).unwrap();
    let mut users_by_level: HashMap&lt;String, Vec&lt;User&gt;&gt; = HashMap::new();

    for user in users.iter() {
        users_by_level
            .entry(user.level.clone())
            .or_insert(Vec::new())
            .push(user.clone());
    }
}

The user struct can derive the clone trait since it is made up of types that can be cloned (in this case owned Strings). Then in the for loop when you insert user as the value, you use the .clone() method to copy the user to mutable HashMap.

huangapple
  • 本文由 发表于 2023年7月28日 00:43:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76781857.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定