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

如何对含字符串与Decimal类型的Rust复合结构体数组排序?

问题描述

我定义了包含字符串与Decimal类型的复合结构体:

use rust_decimal::prelude::*;

#[derive(Deserialize, Serialize, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct Row {
    pub acc_code: String,
    pub acc_type: String,
    pub acc_name: String,
    pub before: Decimal,
    pub total: Decimal,
    pub after: Decimal,
}

我用Vector的sort_by_key方法对结构体数组排序,对字符串类型字段(acc_code、acc_type、acc_name)排序正常,但对Decimal类型字段(total、after、before)排序时,因为把数值转成了字符串,导致排序逻辑错误(比如[1000, 4, 500, 6]的排序结果不符合数值大小)。由于sort_by_key要求返回统一类型,没法同时用字符串和数值类型,请问怎么实现跨字段的正确排序?


解决方案

方法一:用sort_by替代sort_by_key

sort_by允许自定义比较逻辑,不需要统一的键类型,直接针对不同字段用对应类型的比较方法:

let sort_by = Some("acc_code");
let mut container: Vec<Row> = vec![];

if let Some(sort_by) = sort_by {
    container.sort_by(|a, b| match sort_by {
        "acc_code" => a.acc_code.cmp(&b.acc_code),
        "acc_type" => a.acc_type.cmp(&b.acc_type),
        "acc_name" => a.acc_name.cmp(&b.acc_name),
        "before" => a.before.cmp(&b.before),
        "total" => a.total.cmp(&b.total),
        "after" => a.after.cmp(&b.after),
        _ => a.acc_code.cmp(&b.acc_code),
    });
}

这种方式最直接,字符串字段用String::cmp,Decimal字段用Decimal::cmp,完全符合各自的排序规则,没有类型转换带来的问题,还能避免sort_by_key中字符串克隆的开销。

方法二:用枚举作为统一键类型

如果一定要用sort_by_key,可以定义枚举封装不同类型的键,并为枚举实现Ord trait(注意:排序时只会针对同一字段,不会出现跨类型的枚举变体比较,所以无需额外处理跨类型逻辑):

use rust_decimal::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct Row {
    pub acc_code: String,
    pub acc_type: String,
    pub acc_name: String,
    pub before: Decimal,
    pub total: Decimal,
    pub after: Decimal,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
enum SortKey {
    Str(String),
    Num(Decimal),
}

// 排序逻辑
let sort_by = Some("acc_code");
let mut container: Vec<Row> = vec![];

if let Some(sort_by) = sort_by {
    container.sort_by_key(|r| match sort_by {
        "acc_code" => SortKey::Str(r.acc_code.clone()),
        "acc_type" => SortKey::Str(r.acc_type.clone()),
        "acc_name" => SortKey::Str(r.acc_name.clone()),
        "before" => SortKey::Num(r.before),
        "total" => SortKey::Num(r.total),
        "after" => SortKey::Num(r.after),
        _ => SortKey::Str(r.acc_code.clone()),
    });
}

这种方式需要额外定义枚举,比sort_by繁琐,仅在必须使用sort_by_key的场景下考虑。


推荐方案

优先选方法一,简洁高效,直接利用各类型原生的比较逻辑,还能减少不必要的内存开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:24:23