You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中将扁平记录Vec转换为嵌套结构体数组?

在Rust中手动将扁平记录集合转换为嵌套结构体数组的惯用方式

我有一个扁平的Vec<Record>集合,其中每条记录同时包含预约(Appointment)和服务(Service)的信息——相同a_id的记录属于同一个预约。需要手动将其转换为嵌套的Vec<Appointment>结构,每个Appointment包含预约的基础信息,以及对应的Vec<Service>列表,且不使用任何额外第三方库。

原始扁平记录结构

// 伪代码
use uuid::Uuid;
use chrono::NaiveTime;
use rust_decimal::Decimal;

struct Record {
    a_id: Uuid,
    a_working_day_id: Uuid,
    a_client_id: Uuid,
    a_start_time: NaiveTime,
    a_end_time: NaiveTime,
    s_id: Uuid,
    s_name: String,
    s_price: Decimal,
    s_duration: i32,
}

let records: Vec<Record> = vec![
    // 属于预约#1的记录
    Record { /* 字段值 */ },
    Record { /* 字段值 */ },
    Record { /* 字段值 */ },
    
    // 属于预约#2的记录
    Record { /* 字段值 */ },
    Record { /* 字段值 */ },
    Record { /* 字段值 */ },

    // 属于预约#3的记录
    Record { /* 字段值 */ },
    Record { /* 字段值 */ },
    Record { /* 字段值 */ },
];

目标嵌套结构体定义

// 伪代码
struct Appointment {
    pub id: Uuid,              // 对应Record的a_id
    pub working_day_id: Uuid,  // 对应Record的a_working_day_id
    pub client_id: Uuid,       // 对应Record的a_client_id
    pub start_time: NaiveTime, // 对应Record的a_start_time
    pub end_time: NaiveTime,   // 对应Record的a_end_time
    pub services: Vec<Service>,
}

struct Service {
    pub id: Uuid,              // 对应Record的s_id
    pub name: String,          // 对应Record的s_name
    pub price: Decimal,        // 对应Record的s_price
    pub duration: i32,         // 对应Record的s_duration
}

惯用实现方案

核心思路是利用HashMap按预约ID(a_id)分组,遍历每条扁平记录时提取服务信息,合并预约基础信息到对应分组,最后将HashMap的值转换为目标数组。

完整示例代码

use std::collections::HashMap;
use uuid::Uuid;
use chrono::NaiveTime;
use rust_decimal::Decimal;

// 原始扁平记录结构
struct Record {
    a_id: Uuid,
    a_working_day_id: Uuid,
    a_client_id: Uuid,
    a_start_time: NaiveTime,
    a_end_time: NaiveTime,
    s_id: Uuid,
    s_name: String,
    s_price: Decimal,
    s_duration: i32,
}

// 目标嵌套结构体
struct Appointment {
    pub id: Uuid,
    pub working_day_id: Uuid,
    pub client_id: Uuid,
    pub start_time: NaiveTime,
    pub end_time: NaiveTime,
    pub services: Vec<Service>,
}

struct Service {
    pub id: Uuid,
    pub name: String,
    pub price: Decimal,
    pub duration: i32,
}

fn convert_records_to_appointments(records: Vec<Record>) -> Vec<Appointment> {
    let mut appointment_map: HashMap<Uuid, Appointment> = HashMap::new();

    for record in records {
        // 提取当前记录的服务信息
        let service = Service {
            id: record.s_id,
            name: record.s_name,
            price: record.s_price,
            duration: record.s_duration,
        };

        // 查找或创建对应预约:存在则复用,不存在则初始化新预约
        let appointment = appointment_map.entry(record.a_id).or_insert_with(|| Appointment {
            id: record.a_id,
            working_day_id: record.a_working_day_id,
            client_id: record.a_client_id,
            start_time: record.a_start_time,
            end_time: record.a_end_time,
            services: Vec::new(),
        });

        // 将服务添加到预约的服务列表
        appointment.services.push(service);
    }

    // 将HashMap中的预约转换为Vec返回
    appointment_map.into_values().collect()
}

// 使用示例
fn main() {
    // 假设此处已初始化好records集合
    let records: Vec<Record> = vec![/* ... */];
    let appointments = convert_records_to_appointments(records);
}

关键说明

  • 利用HashMap::entry API高效处理“存在则更新,不存在则插入”的场景,避免重复查找
  • 仅需遍历一次原始记录,时间复杂度为O(n)(n为记录总数)
  • 默认假设同一预约的所有记录基础信息(a_working_day_id、a_client_id等)完全一致,若存在信息冲突,可根据需求添加处理逻辑(如保留第一条记录信息、抛出错误等)

内容的提问来源于stack exchange,提问作者Roman Mahotskyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 20:01:14