rust语言学习笔记Trait(十)PartialOrd、Ord(大小比较)
2026/5/25 23:30:10 网站建设 项目流程

在 Rust 中,PartialOrdOrd是定义类型排序能力的两个核心 trait。简单说:‌**PartialOrd表示“部分排序”,Ord表示“全序”**‌。所有需要比较大小、排序的数据结构都离不开它们。

继承关系:

PartialEqEqPartialEqPartialOrd// PartialOrd 必须实现 PartialEqPartialEqEqPartialOrdOrd// Ord 必须实现 PartialEq、 Eq 、PartialOrd

1、x.partial_cmp(&y)方法,大小比较

x.partial_cmp(&y)的返回类型是Option<Ordering>,所以一共有 ‌4 种可能的结果‌:

结果含义
Some(Ordering::Less)x小于y
Some(Ordering::Equal)x等于y
Some(Ordering::Greater)x大于y
Nonexy无法比较‌(例如涉及NaN
fnmain(){letx=50;lety=60;println!("{:?}",x.partial_cmp(&y));// Some(Less)}

1、PartialOrd——部分排序

  • PartialOrd‌**要求类型必须先实现PartialEq**‌,因为排序的前提是能判断相等。

  • 部分排序允许两个值之间‌可能无法比较‌。最典型的例子就是浮点数中的NaNNaN与任何值(包括它自己)比较都是无意义的,因此浮点数只能实现PartialOrd

  • PartialOrdtrait 的核心方法是partial_cmp

fnpartial_cmp(&self,other:&Self)->Option<Ordering>;
  • 它返回Option<Ordering>,当值无法排序时返回None
fnmain(){letx=1.0f64;lety=f64::NAN;println!("{:?}",x.partial_cmp(&y));// None}
  • PartialOrd还提供了<><=>=这些比较运算符的默认实现,内部都依赖partial_cmp

(1)x.partial_cmp(&y)方法,大小比较

x.partial_cmp(&y)的返回类型是Option<Ordering>,所以一共有 ‌4 种可能的结果‌:

结果含义
Some(Ordering::Less)x小于y
Some(Ordering::Equal)x等于y
Some(Ordering::Greater)x大于y
Nonexy无法比较‌(例如涉及NaN
fnmain(){letx=50;lety=60;println!("{:?}",x.partial_cmp(&y));// Some(Less)}

(2)自动派生PartialOrd

当在结构体或枚举上#[derive(PartialEq, PartialOrd)]时:

  • 结构体‌:按照字段从上到下的声明顺序,依次比较每个字段,第一个不等字段的结果即为整体结果。

    • #[derive(PartialEq, PartialOrd)]structMyStruct{a:i32,b:i32,}fnmain(){letm1=MyStruct{a:20,b:55};letm2=MyStruct{a:20,b:10};println!("{:?}",m1.partial_cmp(&m2));// Some(Greater)}
  • 枚举‌:按照变体从上到下的声明顺序,靠前的变体小于靠后的变体;同一变体内的字段再按顺序比较。

    • #[derive(PartialEq, PartialOrd)]enumMyEnum{BBB,AAA,CCC,}fnmain(){letm1=MyEnum::BBB;letm2=MyEnum::AAA;letm3=MyEnum::CCC;println!("{:?}",m1.partial_cmp(&m2));// Some(Less)println!("{:?}",m2.partial_cmp(&m3));// Some(Less)}

2、Ord——全部排序

全序要求任意两个值‌都可以且必须能排出确定的大小‌,满足三个性质:

  • 完全性‌:对于任意aba<ba==ba>b三者有且只有一个成立。
  • 反对称性‌:若a<b则不可能a>b
  • 传递性‌:若a<bb<ca<c

Ord的核心方法是cmp,直接返回Ordering(不再有Option):

fncmp(&self,other:&Self)->Ordering;

因为任何两个值都能比较,所以cmp总是能返回LessEqualGreater

Ord还提供了实用的maxmin方法,可以直接找出两个值中的较大者或较小者。

(1)x.cmp(&y)方法,大小比较

x.cmp(&y)的返回类型是Ordering,所以一共有 ‌4 种可能的结果**‌:

结果含义
Ordering::Lessx小于y
Ordering::Equalx等于y
Ordering::Greaterx大于y
fnmain(){letx=50;lety=60;println!("{:?}",x.cmp(&y));// Less}

(2)自动派生Ord

当在结构体或枚举上#[derive(PartialEq, PartialOrd, Eq, Ord)]时:

  • 结构体‌:按照字段从上到下的声明顺序,依次比较每个字段,第一个不等字段的结果即为整体结果。

    • #[derive(PartialEq, PartialOrd, Eq, Ord)]structMyStruct{a:i32,b:i32,}fnmain(){letm1=MyStruct{a:20,b:55};letm2=MyStruct{a:20,b:10};println!("{:?}",m1.cmp(&m2));// Greater}
  • 枚举‌:按照变体从上到下的声明顺序,靠前的变体小于靠后的变体;同一变体内的字段再按顺序比较。

    • #[derive(PartialEq, PartialOrd, Eq, Ord)]enumMyEnum{BBB,AAA,CCC,}fnmain(){letm1=MyEnum::BBB;letm2=MyEnum::AAA;letm3=MyEnum::CCC;println!("{:?}",m1.cmp(&m2));// Lessprintln!("{:?}",m2.cmp(&m3));// Less}

3、手动实现PartialOrdOrd,比较一个值

// PartialOrd 必须实现 PartialEq// Ord 必须实现 PartialEq、 Eq、PartialOrd#[derive(PartialEq, Eq)]// 通过派生实现 PartialEq, EqstructMyStruct{name:String,age:i32,}// 手动实现 PartialOrdimplPartialOrdforMyStruct{fnpartial_cmp(&self,other:&Self)->Option<std::cmp::Ordering>{self.age.partial_cmp(other.age)// 仅比较年龄}}// 手动实现 OrdimplOrdforMyStruct{fncmp(&self,other:&Self)->std::cmp::Ordering{self.age.cmp(other.age)// 仅比较年龄}}}fnmain(){letm1=MyStruct{name:"小李".to_string(),age:55};letm2=MyStruct{name:"小刘".to_string(),age:10};letm3=MyStruct{name:"小王".to_string(),age:80};println!("{:?}",m1.partial_cmp(&m2));// Some(Greater)println!("{:?}",m1.partial_cmp(&m3));// Some(Less)println!("{:?}",m1.cmp(&m2));// Greaterprintln!("{:?}",m1.cmp(&m3));// Less}

4、手动实现Ord,比较多个值

// Ord 必须实现 PartialEq、 Eq、PartialOrd#[derive(PartialEq, Eq, PartialOrd)]structMyStruct{a:i32,b:i32,c:i32,}// 手动实现 OrdimplOrdforMyStruct{fncmp(&self,other:&Self)->std::cmp::Ordering{self.b.cmp(&other.b)// 先比较 b.then(self.c.cmp(&other.c))// 再比较 c.then(self.a.cmp(&other.a))// 最后比较 a}}fnmain(){letm1=MyStruct{a:10,b:5,c:8};letm2=MyStruct{a:5,b:8,c:8};letm3=MyStruct{a:15,b:5,c:4};println!("{:?}",m1.partial_cmp(&m2));// Some(Greater) 自动派生 abc顺序 m1.a > m2.aprintln!("{:?}",m1.partial_cmp(&m3));// Some(Less) 自动派生 abc顺序 m1.a < m3.aprintln!("{:?}",m1.cmp(&m2));// Less m1.b < m2.bprintln!("{:?}",m1.cmp(&m3));// Greater m1.c > m3.c}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询