# How to compare enum based on order instead of value?

Following code

``````#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
#[repr(u8)]
pub enum Rank{
Two = b'2',
Three = b'3',
Four = b'4',
Five = b'5',
Six = b'6',
Seven = b'7',
Eight = b'8',
Nine = b'9',
Ten,
Jack = b'J',
Queen = b'Q',
King = b'K',
Ace = b'A',
}

fn main() {

let r1 = Rank::Jack;
let r2 = Rank::Ace;

if r1 < r2 {
println!("{:?} rank is less than {:?}", r1, r2 );
} else {
println!("{:?} rank is greater than {:?}", r1, r2 );
}

}
``````

Above code prints

``````Jack rank is greater than Ace
``````

This is coz, the ascill value of A is less than J. Is there a way to compare enum based on the order in the enum instead of value?

You would need to manually implement the `Ord` trait for your enum.

1 Like

can you please provide same sample or link that would help?

Pro tip: Make sure to get your playground links from the â€śShareâ€ť button, otherwise itâ€™s a generic link to the playgroundâ€™s home page.

Of course you can compare based on the order, but the default implementation will compare enum discriminants numerically, so youâ€™d need to write it yourself.

For your code at hand, if the declaration order is the one youâ€™re most interested in, Iâ€™m wondering why you want this ascii-as-a-byte kind of enum representation in the first place. Maybe you could provide more context as for how thatâ€™s used. If you want to associate the enum variants with string representations (perhaps also including the number `Ten`), then a simple function returning a `&'static str` migth be the most straightforward way.

4 Likes

Do you need `Rank`'s discriminants to be those bytes? I would consider removing the `= b'2'` etc. assignments (after which `PartialOrd` will be derived based on the order the variants are defined) and instead adding some sort of `get_symbol() -> Option<u8>` method to `Rank` that uses a `match` to map variants to bytes.

2 Likes

As-is, the easiest way is probably to offer an inverse translation from your enum to its proper order, and compare based on that

``````impl Rank {
fn enum_index(&self) -> u8 {
match *self {
Rank::Two => 0,
Rank::Three => 1,
Rank::Four => 2,
Rank::Five => 3,
Rank::Six => 4,
Rank::Seven => 5,
Rank::Eight => 6,
Rank::Nine => 7,
Rank::Ten => 8,
Rank::Jack => 9,
Rank::Queen => 10,
Rank::King => 11,
Rank::Ace => 12,
}
}
}
impl Ord for Rank {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.enum_index().cmp(&other.enum_index())
}
}
impl PartialOrd for Rank {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(&other))
}
}
``````

Though if such a translation is necessary anyways, as noted above, I feel like doing the inverse and skipping on using a `repr` and `= b'â€¦'` values instead seems nicer.

3 Likes

I started with assumption that I could use the ascii value to print. But, its of no use, especially considering 10.

Thanks, once discriminants are removed & after writing own to_sting function to print, its good now.

Thanks !!

An alternative to the function mapping enum variants to strings is just using a const array like:

``````const CARD_NAMES: [&str; 13] = [
"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A",
];
``````

then you can use an enum repr to index into that

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.