DEV Community

Thiago Massari Guedes
Thiago Massari Guedes

Posted on

How to sort a vector of a custom struct in Rust

How to sort a vector of a custom struct in Rust

When implementing tags for Texted2, I had a list of tags being:

let tags: Vec<(&str, u32)>; // Tag name, number of posts containing this tag
Enter fullscreen mode Exit fullscreen mode

And I need to sort it by the second item of the tuple, the tag count.

Changing the comparing function with a Lambda

As usual, it was simpler than I expected. This is the code to sort

First: Let's say I want to sort from the smaller count to the larger count

 // Adding some types to simplify the reading
freq_list.sort_by(|a: &(&str, u32), b: &(&str, u32)| {
    let (_tag_name_a: &&str, count_a: &u32) = a;
    let (_tag_name_b: &&str, count_b: &u32) = b;
    count_a.cmp(count_b)
});
Enter fullscreen mode Exit fullscreen mode

This is the signature of the method sort_by:

pub fn sort_by<F>(&mut self, mut compare: F)
where
    F: FnMut(&T, &T) -> Ordering,
{
    stable_sort(self, |a, b| compare(a, b) == Less);
}
Enter fullscreen mode Exit fullscreen mode

And Ordering is an enum with the values Less, Equal and Greater

Changing our Lambda to sort in descending order

As the cmp method returns Ordering, to invert the ordering to list the tags from the most common to the least common, it was also quite simple. I just need to invert the Ordering values.

freq_list.sort_by(|a, b| {
    let (_tag_name_a, count_a) = a;
    let (_tag_name_b, count_b) = b;
    match count_a.cmp(count_b) {
        Ordering::Less => Ordering::Greater,
        Ordering::Equal => Ordering::Equal,
        Ordering::Greater => Ordering::Less,
    }
});
Enter fullscreen mode Exit fullscreen mode

Note how clear it is that we're changing the order by using a match block.

I hope it is useful to you and reach me out for any comments!


Link in the author's blog: https://www.thiagocafe.com/view/20240308_how_to_sort_a_vector_of_a_custom_struct_in_rust/

Top comments (5)

Collapse
 
thiagomg profile image
Thiago Massari Guedes

That's a nice simpler alternative, indeed :)
I find it less readable, however.

Collapse
 
lexlohr profile image
Alex Lohr

Why is that? Also, if you are concerned it could be misunderstood, put the lambda in a separate named function called reverse_order or something.

Collapse
 
thiagomg profile image
Thiago Massari Guedes

Now this is on the preference realm. After living many, many years in the low latency world, where things are not super readable, I like explicit things when possible, such as the block:

Ordering::Less => Ordering::Greater,
Ordering::Greater => Ordering::Less,
Enter fullscreen mode Exit fullscreen mode

And, of course, that's my personal preference :) Both are ok - and I agree with you that the function name is better using a descriptive name.

Thread Thread
 
thiagomg profile image
Thiago Massari Guedes

And thanks for the feedback!

Collapse
 
lexlohr profile image
Alex Lohr

Wouldn't it be simpler to count_b.cmp(count_a) to change the ordering?