1

I am trying to sort a vector of Substance structs:

#[derive(Debug, PartialOrd, PartialEq)]
struct Substance {
    price: i32,
    mass_kg: i32,
    price_per_kg: f64,
}

by price_per_kg my current sorting code is:

// `substances` is a `vec` of `Substance`'s
substances.sort_unstable_by_key(|price_per_kg| price_per_kg);

This fails as the method requires the Ord trait. However, as f64 doesn't implement Eq I can't derive Ord and therefore I seemingly can't use this method.

Could you please let me know how I can do this sorting? Thanks,

Pioneer_11
  • 670
  • 4
  • 19

1 Answers1

1

f64 doesn't implement Ord because of NaN... In practice,this means that Rust expects you to instruct it about how to handle if you need to compare such a float. An easy way is to assume you don't have any NaN value and panicking if you do, as follows:

impl Ord for Substance {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(self, other).unwrap()
    }
}

This way, you naturally extend the partial ordering ignoring an annoyance of working with floats.

jthulhu
  • 7,223
  • 2
  • 16
  • 33
  • That makes sense, but the code you suggest still requires the `Eq` trait, which I do not have and cannot derive. – Pioneer_11 Mar 22 '23 at 22:14
  • 1
    `Eq` is just an empty marker trait, so it's easy to implement yourself: `impl Eq for Substance {}` ([playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=9482a28c6782ffd64e7762ee8af288c7)). – Jmb Mar 23 '23 at 07:59
  • 1
    @Pioneer_11 also note that there are some crates that already do these kind of solutions, and that also offer other solutions (for instance, consider `NaN` as the greatest float), so using them is probably more convenient. I just gave you this code as a pedagogical example. See [`ordered_float`](https://docs.rs/ordered-float/latest/ordered_float/) for instance. – jthulhu Mar 23 '23 at 12:35
  • For instance, you may want to represent a float as a `Option`, which is a better way to encode the failure float `NaN`, but which is also (very slightly) slower if you do heavy computations on floats. – jthulhu Mar 23 '23 at 12:38