How to combine two cmp conditions in `Ord::cmp()`

Viewed 118

I'm trying to combine more than one condition when implementing cmp() and eq() from Ord and PartialEq traits. Something that looks like this:

self.id.cmp(&other.id) && self.age.cmp(&other.age)

Here's a working example minus the combined condition:

use std::cmp::Ordering;

#[derive(Debug, Clone, Eq)]
pub struct Person {
    pub id: u32,
    pub age: u32,
}

impl Person {
    pub fn new(id: u32, age: u32) -> Self {
        Self {
            id,
            age,
        }
    }
}

impl Ord for Person {
    fn cmp(&self, other: &Self) -> Ordering {
        self.id.cmp(&other.id)
    }
}

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

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

Ord doesn't return a boolean, it returns an Ordering which can be Less, Equal or Greater, so you can't just use && on it.

Ordering has a few methods, one of which is then (and its companion then_with), which does the usual "sort by one field, and then by another one" operation. Your example then becomes

    fn cmp(&self, other: &Self) -> Ordering {
        self.id.cmp(&other.id)
            .then(self.age.cmp(&other.age))
    }
Related