Sling Academy
Home/Rust/Sorting a Rust Vec with sort, sort_by, and sort_by_key

Sorting a Rust Vec with sort, sort_by, and sort_by_key

Last updated: January 04, 2025

Sorting a vector in Rust is a common and crucial operation, especially when dealing with collections of data that need to be ordered for user display, algorithmic optimization, or other purposes. Rust provides several powerful built-in methods to sort a vector: sort, sort_by, and sort_by_key. In this article, we’ll explore each of these methods with examples to understand how they work.

Understanding Vec in Rust

Before diving into sorting, let’s briefly discuss what a Vec is in Rust. A Vec (short for vector) is a heap-allocated, resizable array type provided by Rust's standard library. It allows you to grow or shrink its size dynamically and is a staple in managing collections of values.

Sorting with sort

The simplest way to sort a Vec in Rust is by using the sort method. This method sorts the elements of the Vec in-place in ascending order, utilizing the natural ordering of the elements.

fn main() {
    let mut numbers = vec![10, 5, 3, 12, 7];
    numbers.sort();
    println!("Sorted numbers: {:?}", numbers);
}

In this code snippet, we initialize a Vec of integers and use sort(), which sorts them in-place. The output is:

Sorted numbers: [3, 5, 7, 10, 12]

Custom Sorting with sort_by

The sort_by method provides more flexibility by allowing you to sort the Vec based on a custom comparator function. This is useful when you want to sort data using criteria other than natural order.

fn main() {
    let mut words = vec!["apple", "banana", "cherry", "date"];
    words.sort_by(|a, b| b.len().cmp(&a.len()));
    println!("Sorted words by length descending: {:?}", words);
}

This example sorts the Vec of strings based on the string lengths in descending order.

Sorting by a Key with sort_by_key

The sort_by_key method is very similar to sort_by, but it abstracts the comparator function into a single operation: extracting a key by which to sort. It is generally simpler for common transformations.

fn main() {
    let mut fruits = vec!["banana", "apple", "cherry", "date"];
    fruits.sort_by_key(|w| w.len());
    println!("Sorted fruits by length ascending: {:?}", fruits);
}

This snippet sorts our list of fruits by the length of each string in ascending order.

Performance Implications

All three sorting methods rearrange the Vec in-place, meaning no additional memory is allocated. However, the efficiency of sorting depends on the nature of the comparator. Using sort is ideal when dealing with simple, naturally ordered data types such as integers or &str. On the other hand, sort_by and sort_by_key are better for complex ordering or when sorting large, elaborate data structures.

Conclusion

Sorting vectors in Rust is straightforward and versatile thanks to the multiple methods catered to different needs. While sort is perfect for basic, ascending sorts, sort_by and sort_by_key open up a world of custom sorting options, ideally suited for complex requirements, focusing on detailed customization and key extraction, respectively. Whether managing a list of numbers or sorting strings by criteria like length or alphabetical order, Rust provides the tools to do it efficiently and concisely.

Next Article: Rust - Searching in vectors: find, position, and binary_search for sorted data

Previous Article: Rust: Leveraging split, split_mut, and chunks for partial vector processing

Series: Collections in Rust

Rust

You May Also Like

  • E0557 in Rust: Feature Has Been Removed or Is Unavailable in the Stable Channel
  • Network Protocol Handling Concurrency in Rust with async/await
  • Using the anyhow and thiserror Crates for Better Rust Error Tests
  • Rust - Investigating partial moves when pattern matching on vector or HashMap elements
  • Rust - Handling nested or hierarchical HashMaps for complex data relationships
  • Rust - Combining multiple HashMaps by merging keys and values
  • Composing Functionality in Rust Through Multiple Trait Bounds
  • E0437 in Rust: Unexpected `#` in macro invocation or attribute
  • Integrating I/O and Networking in Rust’s Async Concurrency
  • E0178 in Rust: Conflicting implementations of the same trait for a type
  • Utilizing a Reactor Pattern in Rust for Event-Driven Architectures
  • Parallelizing CPU-Intensive Work with Rust’s rayon Crate
  • Managing WebSocket Connections in Rust for Real-Time Apps
  • Downloading Files in Rust via HTTP for CLI Tools
  • Mocking Network Calls in Rust Tests with the surf or reqwest Crates
  • Rust - Designing advanced concurrency abstractions using generic channels or locks
  • Managing code expansion in debug builds with heavy usage of generics in Rust
  • Implementing parse-from-string logic for generic numeric types in Rust
  • Rust.- Refining trait bounds at implementation time for more specialized behavior