Rust lenguaje desde la entrada hasta la serie maestra: ¿cómo juzgar si los objetos son iguales?

rust_tutorial_logo.pngEn el lenguaje Rust, PartialEq y Eq son dos rasgos muy importantes. Se usan para comparar valores de tipos, PartialEq se usa para comparar igualdad parcial (no necesariamente igualdad exacta), y Eq se usa para comparar igualdad exacta.

En Rust, cualquier tipo puede implementar PartialEq y Eq, por lo que estos dos rasgos son muy flexibles.

Uso básico

comparar enteros

fn main() {
    let a = 10;
    let b = 20;
    if a == b {
        println!("a equals b");
    } else {
        println!("a does not equal b");
    }
}
复制代码

producción:

a does not equal b
复制代码

comparar cadenas

fn main() {
    let a = "hello";
    let b = "world";
    if a == b {
        println!("a equals b");
    } else {
        println!("a does not equal b");
    }
}
复制代码

producción:

a does not equal b
复制代码

Comparar tipos personalizados

#[derive(PartialEq, Eq)]
struct Person {
    name: String,
    age: u8,
}

fn main() {
    let p1 = Person {
        name: "Alice".to_string(),
        age: 30,
    };
    let p2 = Person {
        name: "Bob".to_string(),
        age: 30,
    };
    if p1 == p2 {
        println!("p1 equals p2");
    } else {
        println!("p1 does not equal p2");
    }
}
复制代码

producción:

p1 does not equal p2
复制代码

Comparar números de punto flotante

fn main() {
    let a = 0.1 + 0.2;
    let b = 0.3;
    if a == b {
        println!("a equals b");
    } else {
        println!("a does not equal b");
    }
}
复制代码

producción:

a does not equal b
复制代码

función de comparación personalizada

#[derive(PartialEq, Eq)]
struct Person {
    name: String,
    age: u8,
}

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

impl Eq for Person {}

fn main() {
    let p1 = Person {
        name: "Alice".to_string(),
        age: 30,
    };
    let p2 = Person {
        name: "Bob".to_string(),
        age: 30,
    };
    if p1 == p2 {
        println!("p1 equals p2");
    } else {
        println!("p1 does not equal p2");
    }
}
复制代码

producción:

p1 equals p2
复制代码

Comparación de tipos enumerados

#[derive(PartialEq, Eq)]
enum Color {
    Red,
    Blue,
}

fn main() {
    let c1 = Color::Red;
    let c2 = Color::Blue;
    if c1 == c2 {
        println!("c1 equals c2");
    } else {
        println!("c1 does not equal c2");
    }
}
复制代码

producción:

c1 does not equal c2
复制代码

Utilice la macro assert_eq!

fn main() {
    let a = 10;
    let b = 20;
    assert_eq!(a, b);
}
复制代码

producción:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `10`,
 right: `20`', src/main.rs:4:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
复制代码

Utilice la macro assert_ne!

fn main() {
    let a = 10;
    let b = 20;
    assert_ne!(a, b);
}
复制代码

producción:

thread 'main' panicked at 'assertion failed: `(left != right)`
  left: `10`,
 right: `10`', src/main.rs:4:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
复制代码

Uso avanzado

función de comparación personalizada

#[derive(PartialEq, Eq)]
struct Person {
    name: String,
    age: u8,
}

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

impl Eq for Person {}

fn main() {
    let p1 = Person {
        name: "Alice".to_string(),
        age: 30,
    };
    let p2 = Person {
        name: "Bob".to_string(),
        age: 40,
    };
    if p1 == p2 {
        println!("p1 equals p2");
    } else {
        println!("p1 does not equal p2");
    }
}
复制代码

producción:

p1 does not equal p2
复制代码

usar genéricos

#[derive(PartialEq, Eq)]
struct Pair<T> {
    first: T,
    second: T,
}

fn main() {
    let p1 = Pair {
        first: 1,
        second: 2,
    };
    let p2 = Pair {
        first: 2,
        second: 1,
    };
    if p1 == p2 {
        println!("p1 equals p2");
    } else {
        println!("p1 does not equal p2");
    }
}
复制代码

producción:

p1 does not equal p2
复制代码

Usando PartialOrd y Ord

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct Person {
    name: String,
    age: u8,
}

fn main() {
    let p1 = Person {
        name: "Alice".to_string(),
        age: 30,
    };
    let p2 = Person {
        name: "Bob".to_string(),
        age: 40,
    };
    if p1 < p2 {
        println!("p1 is younger than p2");
    } else {
        println!("p1 is older than or equal to p2");
    }
}
复制代码

producción:

p1 is younger than p2
复制代码

Uso de depuración y visualización

#[derive(Debug, PartialEq, Eq)]
struct Person {
    name: String,
    age: u8,
}

use std::fmt;

impl fmt::Display for Person {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} ({})", self.name, self.age)
    }
}

fn main() {
    let p1 = Person {
        name: "Alice".to_string(),
        age: 30,
    };
    let p2 = Person {
        name: "Bob".to_string(),
        age: 40,
    };
    println!("p1: {}", p1);
    println!("p2: {}", p2);
}
复制代码

producción:

p1: Alice (30)
p2: Bob (40)
复制代码

Mejores prácticas

Al implementar PartialEq y Eq, se deben considerar los siguientes puntos:

  • Para los tipos personalizados, se deben comparar todas las variables miembro, no solo algunas.
  • Para números de coma flotante, se deben usar comparaciones aproximadas en lugar de comparaciones exactas.
  • Para los tipos de enumeración, se deben comparar todas las variables miembro, no solo el valor de la enumeración en sí.
  • Si el tipo a comparar implementa PartialOrd y Ord, estos dos rasgos deben usarse primero.

en conclusión

En el lenguaje Rust, PartialEq y Eq son rasgos muy importantes para comparar valores de tipos. Estos dos rasgos son tan flexibles que cualquier tipo puede implementarlos. Al implementar PartialEq y Eq, debe considerar las características del tipo, comparar todas las variables miembro, usar una comparación aproximada, etc.

Supongo que te gusta

Origin juejin.im/post/7222294792893136933
Recomendado
Clasificación