如何在Rust中对结构体向量使用group_by实现用户角色数据聚合
实现方案
Rust 标准库迭代器自带的group_by仅对相邻且相同分组键的元素生效,如果你不能保证输入数据已经按user_id排序,更推荐用HashMap实现全局分组:
方案1:HashMap实现(推荐,无排序要求、性能更高)
该方案直接转移元素所有权,无额外字符串拷贝开销:
use std::collections::HashMap; #[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(), }, Temp { user_id: 2, username: "demo".to_string(), role_id: 3, role: "test3".to_string(), }, ]; let mut groups: HashMap<i32, (String, Vec<Role>)> = HashMap::new(); for temp in temps_data { // 按user_id分组,不存在则初始化用户信息和空角色列表 let entry = groups.entry(temp.user_id).or_insert((temp.username, Vec::new())); // 向当前用户的角色列表追加角色 entry.1.push(Role { id: temp.role_id, role: temp.role, }); } // 将HashMap转换为目标User向量格式 let result: Vec<User> = groups.into_iter() .map(|(user_id, (username, roles))| User { id: user_id, username, roles, }) .collect(); // 打印验证结果 println!("{:#?}", result); }
方案2:标准库group_by实现(需提前排序)
如果确定要用迭代器的group_by方法,必须先对输入数据按user_id排序,否则同一个用户的非相邻数据会被拆分为多个分组:
// 先按user_id对源数据排序 let mut sorted_temps = temps_data; sorted_temps.sort_by_key(|temp| temp.user_id); let result: Vec<User> = sorted_temps // 相邻元素user_id相同则分为一组 .group_by(|a, b| a.user_id == b.user_id) .map(|group| { let first_item = group.first().unwrap(); // 遍历组内所有元素生成角色列表 let roles = group.iter() .map(|temp| Role { id: temp.role_id, role: temp.role.clone(), }) .collect(); User { id: first_item.user_id, username: first_item.username.clone(), roles, } }) .collect();
内容的提问来源于stack exchange,提问作者igor
相关产品推荐
相关产品推荐

