Day 13d: Advanced Vector Manipulation – Sorting, Searching, and Reversing
Introduction
Vectors in Rust offer a rich set of methods for data manipulation. Today, we will focus on advanced techniques for working with vectors, specifically sorting, searching, and reversing. These operations allow you to manage and manipulate large datasets efficiently, making vectors highly versatile.
Let’s explore each operation in detail, along with code examples.
Sorting Vectors
Rust provides two methods for sorting vectors: sort()
for default sorting and sort_by()
for custom sorting logic.
sort()
Thesort()
method sorts the vector in place using Rust's default ordering, which typically follows lexicographical order for strings and numerical order for numbers.fn main() { let mut numbers = vec![3, 5, 1, 2, 4]; numbers.sort(); println!("{:?}", numbers); // Output: [1, 2, 3, 4, 5] }
sort_by()
If you need custom sorting logic, such as sorting in descending order or by specific fields in a struct,sort_by()
allows you to pass a closure.fn main() { let mut numbers = vec![3, 5, 1, 2, 4]; numbers.sort_by(|a, b| b.cmp(a)); // Sort in descending order println!("{:?}", numbers); // Output: [5, 4, 3, 2, 1] }
Searching Vectors
Vectors provide several methods to search for elements. Some of the most useful are contains()
, position()
, and binary_search()
.
contains()
Thecontains()
method checks if a particular value exists in the vector. This method is simple but performs a linear search.fn main() { let numbers = vec![1, 2, 3, 4, 5]; let has_three = numbers.contains(&3); println!("Contains 3: {}", has_three); // Output: Contains 3: true }
iter().position()
Theposition()
method returns the index of the first occurrence of a value. If the value is not found, it returnsNone
.fn main() { let numbers = vec![1, 2, 3, 4, 5]; if let Some(pos) = numbers.iter().position(|&x| x == 3) { println!("Found 3 at position: {}", pos); // Output: Found 3 at position: 2 } else { println!("3 not found"); } }
binary_search()
If the vector is sorted,binary_search()
can be used to find an element efficiently with a logarithmic time complexity. It returns aResult
, whereOk
contains the index of the element, andErr
contains the index where the element could be inserted while maintaining order.fn main() { let numbers = vec![1, 2, 3, 4, 5]; match numbers.binary_search(&3) { Ok(index) => println!("Found 3 at index: {}", index), // Output: Found 3 at index: 2 Err(_) => println!("3 not found"), } }
Reversing Vectors
Reversing a vector in Rust is straightforward using the reverse()
method. This in-place operation reverses the order of elements without allocating new memory.
reverse()
fn main() { let mut numbers = vec![1, 2, 3, 4, 5]; numbers.reverse(); println!("{:?}", numbers); // Output: [5, 4, 3, 2, 1] }
Removing Duplicates
Another handy operation is removing adjacent duplicates from a sorted vector using the dedup()
method. It eliminates consecutive duplicates but retains the first occurrence of the element.
dedup()
fn main() { let mut numbers = vec![1, 2, 2, 3, 3, 3, 4, 5]; numbers.dedup(); println!("{:?}", numbers); // Output: [1, 2, 3, 4, 5] }
Conclusion
By mastering sorting, searching, and reversing vectors, you gain powerful tools to handle complex data manipulation in Rust. These operations are highly optimized, making vectors the go-to choice for dynamic data structures.