igor
igor

Reputation: 13

How do I perform a group_by in a vector of structs?

I don't quite understand how to use group_by in Rust (if I understand correctly that I need this function). The example is as abstract as possible. I have a vec of structs:

[
Temp 
 { user_id: 2, username: "test", role_id: 1, role: 123 }, 
Temp 
 { user_id: 2, username: "test", role_id: 2, role: 456 }
]

I want to get

User { 
 user_id: 2, 
 username: "test",
  roles: [
  Role {
   id: 1,
   role: 123
  },
  … etc
 ]
}

Code example (Playground):

#[derive(Debug)]
struct Temp {
    user_id: i32,
    username: String,
    role_id: i32,
    role: String,
}

#[derive(Debug)]
struct User {
    id: i32,
    username: String,
    roles: Vec<Role>,
}

#[derive(Debug)]
struct Role {
    id: i32,
    role: String,
}

fn main() {
    let temps_data = vec![
        Temp {
            user_id: 1,
            username: "test".to_string(),
            role_id: 1,
            role: "test1".to_string(),
        },
        Temp {
            user_id: 1,
            username: "test".to_string(),
            role_id: 2,
            role: "test2".to_string(),
        },
    ];

    // temps_data.group_by(|obj| {
    //     // I don't really understand what should be here
    // })

    // for example, what I want to get
    let result = vec![User {
        id: 1,
        username: "test".to_string(),
        roles: vec![
            Role {
                id: 1,
                role: "test1".to_string(),
            },
            Role {
                id: 2,
                role: "test2".to_string(),
            },
        ],
    }];
}

Upvotes: 1

Views: 2178

Answers (1)

Maxim Gritsenko
Maxim Gritsenko

Reputation: 2592

I believe you are trying to do something like this:

    let res: Vec<User> = temp_data
        .iter()
        .group_by(|x| (x.user_id, x.username.clone()))
        .into_iter()
        .map(|((id, username), group)| User {
            id, 
            username: username, 
            roles: Some(group.map(|u| Role {id: u.role_id, role: u.role.clone()}).collect()),
        })
        .collect();
    println!("{:?}", res);

// [User { id: 1, username: "test", roles: Some([Role { id: 1, role: "test1" }, Role { id: 2, role: "test2" }]) }]

Here is playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=66e1b71bc919ff98e0f100aea3d0351a

Upvotes: 1

Related Questions