如何对含字符串与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
相关产品推荐
相关产品推荐

