当前位置: 首页 > wzjs >正文

浙江省建设监理协会网站广告代理

浙江省建设监理协会网站,广告代理,wordpress建企业商城,网络规划设计的步骤包括哪些要重载比较运算符&#xff0c;需要为类型实现对应的trait。 重载和!&#xff0c;需要实现PartialEq或者Eq 重载<、<、> 、 >&#xff0c;需要实现PartialOrd或者Ord 一、Eq/PartialEq 为什么有两个trait呢&#xff1f; 因为相等关系有两种&#xff1a;一种是完全…

要重载比较运算符,需要为类型实现对应的trait。
重载==和!=,需要实现PartialEq或者Eq
重载<、<=、> 、 >=,需要实现PartialOrd或者Ord

一、Eq/PartialEq

为什么有两个trait呢?
因为相等关系有两种:一种是完全相等关系,一种是部分相等关系。
完全相等关系满足如下三个性质:
自反性:自己一定等于自己,即a=a
对称性:若有a=b,则有b=a
传递性:若有a=bb=c,则有a=c

部分相等关系只满足两个性质:
对称性:若有a=b,则有b=a
传递性:若有a=bb=c,则有a=c

在浮点数类型中有个特殊的值是NaN(Not-a-number),这个值与任何值都不等,包括自己NaN != NaN,它就违背了自反性。所以判断浮点数是否相等就只能使用部分相等关系。

部分相等是全相等关系的子集,也就是说,如果两个元素具有全相等关系,那它们之间也一定有部分相等关系。

(一)PartialEq

是部分相等关系。
这个Trait中定义了两个方法:

pub Trait PartialEq<Rhs: ?Sized = Self> {fn eq(&self, other: &Rhs) -> bool;fn ne(&self, other: &Rhs) -> bool {!self.eq(other)}
}

eq:两个值相等的话就返回true,需要使用者自行重载
ne:两个值不相等的话就返回true,默认已经实现了

所有的基本类型都实现了PartialEq

1.为自定义类型实现PartialEq
可使用#[derive(PartialEq)]由编译器自动实现

 #[derive(PartialEq)] pub struct Person {pub id: u32,pub name: String,pub height: f64,
}

也可以自己手动实现

impl PartialEq for Person {fn eq(&self, other: &Self) -> bool {self.id == other.id}
}

实现时只需要实现eq方法即可,ne我们使用默认的。

实现了PartialEq,就自动重载了==和!=运算符,下面就可以判断是否相等了

fn main() {let p1 = Person {id: 0,name: "John".to_string(),height: 1.2,};let p2 = Person {id: 0,name: "Jack".to_string(),height: 1.4,};println!("p1 == p2 = {}", p1 == p2); // p1 == p2 = true
}

例子

fn main() {let f1 = f32::NAN;let f2 = f32::NAN;if f1 == f2 {println!("NaN竟然可以比较,这很不数学啊!")} else {println!("果然,虽然两个都是NaN,但是它们其实并不相等")}
}

2.比较不同的类型
给Rhs传入不同的类型,就能比较不同类型的相等性。
示例代码如下:

#[derive(PartialEq)]
enum WheelBrand { Bmw, Benz, Michelin, 
}
struct Car { brand: WheelBrand, price: i32, 
}
impl PartialEq<WheelBrand> for Car {fn eq(&self, other: &WheelBrand) -> bool { self.brand == *other }
}
fn main() {let car = Car { brand: WheelBrand::Benz, price: 10000 };let wheel = WheelBrand::Benz; // 比较struct和enumassert!(car == wheel);// assert!(wheel == car); // 无法反过来比较
}

代码仅实现了Car与Wheel的相等性比较,若要反过来比较,还得提供反向的实现,如下:

impl PartialEq<Car> for WheelBrand {fn eq(&self, other: &Car) -> bool {*self == other.brand }
}

(二)Eq

就是完全相等关系

这个trait继承了PartialEq,但没有添加新的方法,这个Trait只是告诉编译器,这是个完全相等关系而非部分相等关系。

pub Trait Eq:PartialEq{}

在标准库中,只有f32和f64没有实现Eq

1.为自定义类型实现Eq
实现Eq不需要额外的代码,只需要实现PartialEq,并添加#[derive(Eq)]就可以了。

实现了Eq的类型自然也重载了 == 和!=运算符,下面就可以判断是否相等了
Rust中HashMap的key要求实现Eq,也就是要能完全相等,而浮点数由于没有实现Eq,因此不能用于HashMap的key

二、Ord / PartialOrd

大小关系也有两种:一种是全序关系,一种是偏序关系。
全序关系有以下性质:

完整的不对称性total antisymmetry:a < b,a == b,a > b这三种结果只有一个是真;
可传递性transitive:如果a < b且b < c那么a < c;

偏序关系有以下性质:

不对称性antisymmetry:如果a < b那么 !(a > b);
可传递性transitive:如果a < b且b < c那么a < c;

还是因为特殊值NaN,NaN < 0 == false并且NaN > 0 == false并且(NaN == 0) == false

(一)PartialOrd

偏序关系

PartialOrd继承了PartialEq,并且新定义了几个方法

pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;fn lt(&self, other: &Rhs) -> bool {matches!(self.partial_cmp(other), Some(Less))}fn le(&self, other: &Rhs) -> bool {matches!(self.partial_cmp(other), Some(Less | Equal))}fn gt(&self, other: &Rhs) -> bool {matches!(self.partial_cmp(other), Some(Greater))}fn ge(&self, other: &Rhs) -> bool {matches!(self.partial_cmp(other), Some(Greater | Equal))}
}

partial_cmp:需要使用者重载,返回两值的比较结果;
lt,le,gt,ge:默认定义好了;

标准库里的所有基本类型都已实现该Trait

1.为自定义类型实现PartialOrd
要实现PartialOrd,必须同时实现PartialEq

可使用#[derive(PartialOrd)]的方法实现该Trait,也可手动实现

impl PartialOrd for Person {fn partial_cmp(&self,other:&Self) -> Option<std::cmp::Ordering> {self.height.partial_cmp(&other.height)}
}

实现PartialOrd只需要实现partial_cmp方法即可,lt(),le(),gt() , ge() 使用默认的

比较结果为Ordering枚举类型:

pub enum Ordering {Less = -1,Equal = 0,Greater = 1,
}

为什么partial_cmp这个方法返回值类型是个Option, 而非直接是一个Ordering值类型?
这仍然与浮点数类型有关, 因为NaN不是一个可以表示的数值, 诸如:3.0 < NaN这样的表达式毫无意义!对于这种情况,partial_cmp就会返回None。
partial_cmp返回一个Option导致一个结果,当结果为None时, 无法决定两个值的排序,即x和y会处于不确定排序。只实现PartialOrd还不足以使你的自定义类型可排序,你还需要实现Ord。

实现了PartialOrd的类型,会自动重载 <、<=、> 、 >= 运算符,下面就可以比较了
例子

fn main() {let p1 = Person {id: 0,name: "John".to_string(),height: 1.2,};let p2 = Person {id: 0,name: "Jack".to_string(),height: 1.4,};println!("p1 < p2 = {}", p1 < p2);println!("p1 <= p2 = {}", p1 <= p2);println!("p1 > p2 = {}", p1 > p2);println!("p1 >= p2 = {}", p1 >= p2);let x: f64 = std::f64::NAN;let y = 1.0f64;assert_eq!(x.partial_cmp(&y), None);
}

2.比较不同类型

(二)Ord

全序关系
Ord继承了PartialOrd和Eq,并且新定义了几个方法:

pub trait Ord: Eq + PartialOrd<Self> {fn cmp(&self, other: &Self) -> Ordering;fn max(self, other: Self) -> Self{...}fn min(self, other: Self) -> Self{...}fn clamp(self, min: Self, max: Self) -> Self{...}
}

cmp:需要使用者重载本方法,返回两值的比较结果;
max,min,clamp:已经定义好了;

在标准库中,只有f32和f64没有实现Ord

1.为自定义类型实现Ord
要实现Ord,必须要同时实现PartialOrd和Eq。实现PartialEq,PartialOrd以及Ord时要特别注意彼此之间不能冲突
例子
vector中的sort方法要求类型实现了Ord

use std::cmp::Ordering;
#[derive(Debug,Eq)]
pub struct Person {pub id: u32,pub name: String,pub height: f64,
}
impl PartialEq<Self> for Person {fn eq(&self, other: &Self) -> bool { self.id == other.id }
}
impl PartialOrd for Person {fn partial_cmp(&self, other: &Self) -> Option<Ordering> {self.id.partial_cmp(&other.id)}
}
impl Ord for Person {fn cmp(&self, other: &Self) -> Ordering {self.id.cmp(&other.id)}
}

实现Ord只需要实现cmp方法即可,max() 和min()使用默认的。

例子

enum BookFormat3 {Paperback,Hardback,Ebook,
}struct Book3 {name: String,format: BookFormat3,
}// -- 先实现 PartialEq
impl PartialEq for Book3 {fn eq(&self, other: &Book3) -> bool {self.name == other.name// 这里假设format字段不要求比较}
}// -- 再实现 Eq
impl Eq for Book3 {}// -- 再实现 Ord
impl Ord for Book3 {fn cmp(&self, other: &Book3) -> Ordering {// 直接调用name(String)的cmp方法(当需要实现Ord时,成员字段一般都实现了Ord,可直接调用其cmp方法)self.name.cmp(&other.name)}
}// -- 最后实现 PartialOrd
impl PartialOrd for Book3 {fn partial_cmp(&self, other: &Book3) -> Option<Ordering> {// 直接调用上面实现的cmp方法Some(self.cmp(&other))}
}

实现Ord的时候需要同时实现PartialOrd,PartialOrd的partial_cmp()内部调用的是Ord的cmp(),理由是既然一开始就想要为类型实现Ord,说明类型是能够得出一个肯定结果的(非None)

实现了Ord之后,会自动重载 <、<=、> 、 >= 运算符,下面就可以比较了
例子

use std::cmp::Ordering;
let x = 1;
let y = 2;
assert_eq!(x.cmp(&y), Ordering::Less);
assert_eq!(y.cmp(&x), Ordering::Greater);
assert_eq!(x.cmp(&x), Ordering::Equal);
assert_eq!((-3).clamp(-2, 1), -2);
assert_eq!(0.clamp(-2, 1), 0);
assert_eq!(2.clamp(-2, 1), 1);
assert_eq!(1.min(2), 1);
assert_eq!(2.min(2), 2);
assert_eq!(1.max(2), 2);
assert_eq!(2.max(2), 2);

例子

fn main() {let mut v = vec![Person {id: 3,name: "".to_string(),height: 3.0,},Person {id: 2,name: "".to_string(),height: 4.0,},Person {id: 1,name: "".to_string(),height: 5.0,},];v.sort();println!("{:?}", v); 
}

2.比较不同类型

三、关于效率

你也许好奇,到底是自己手动实现的效率高, 还是auto-derive效率高?这很难说,不能一概而论,比如:如果你明确定知道一个大struct中只有少数几个成员与此比较直接相关,或者说有决定性, 那么你自己手动实现的版本很可能优于auto-derive版本, 因为auto-derive版本通常会依次比较所有成员,很可能做了无用功。换一个角度说, 尽管auto-derive版本可能会依次检查比较每一个struct成员, 但是因为它可以采用布尔表达式的短路原则, 也许检查第一个成员就停止了,因此也很有可能快于自定义实现版。但是Hash是一个例外,它不允许短路原则,必须所有成员依次都要哈希一次才可以,不能偷懒,但如果你能够只哈希1或2个简单成员而不是大量字符串成员,那么您将很容易击败auto-derive默认实现。

http://www.dtcms.com/wzjs/149647.html

相关文章:

  • 设计网站如何推广方案优化网站的公司哪家好
  • 工信部网站备案查询 手机百色seo外包
  • 自己做的网站被举报违反广告法代做百度首页排名
  • 检察院门户网站建设情况总结网站怎么被收录
  • 香港公司能在国内做网站厦门人才网唯一官方网站
  • 销售网站平台搭建百度竞价托管费用
  • 洛阳鼎和电力建设有限公司网站2023重大新闻事件10条
  • 快速网站排名汉狮公司seo技术专员招聘
  • 非遗网站建设目的国家卫健委每日疫情报告
  • 唐山模板网站建设建站abc官方网站
  • dw做aspx网站怎么做app推广和宣传
  • 网站标题应怎设置网站页面优化方法
  • 成都系统网站建设qq群排名优化软件购买
  • 做互联网网站待遇5月疫情最新消息
  • wordpress 主题没有样式表网络排名优化软件
  • 在线营业执照办理太原百度快速优化
  • 部门网站建设总结手机百度快照
  • 如何推广自己的外贸网站互联网广告推广好做吗
  • 网站注册免费永久查权重的软件
  • 网站域名已经被绑定100个经典创意营销方案
  • 网络程序河北seo人员
  • 网站建设7个基十大接单平台
  • php 网站发布建站seo推广
  • 怎么看网站有没有做301网站优化推广培训
  • 网站建设待遇最佳磁力吧ciliba
  • 做外贸 是否需要做中文网站949公社招聘信息
  • 邯郸建设网站的公司软件外包网
  • 我想找个人做网站品牌广告和效果广告的区别
  • 客服外包服务提升seo排名平台
  • 红十字会三合一网站建设方案专业做网站官网