Sorting and Binary Search on Slices
Sort vectors through their slice methods, and use binary_search only after the slice is sorted according to the same ordering.
What it is
Sorting and searching are methods on [T].
Because Vec<T> dereferences to [T], numbers.sort() is a slice method call.
sort is stable: equal elements keep their relative order.
sort_unstable may reorder equal elements but can be faster and avoid some overhead.
sort_by and sort_by_key let you choose custom ordering.
sort_by_cached_key can help when computing keys is expensive.
binary_search, binary_search_by, and binary_search_by_key search sorted slices.
The search result is Result<usize, usize>: Ok(index) if found, or Err(insertion_index) if absent.
How it works
Sorting mutates the slice in place.
The element type must implement Ord for sort and sort_unstable.
Use sort_by when comparing derived values, reverse order, or floating-point wrappers.
The comparator must define a consistent total order.
For floats, use f32::total_cmp or f64::total_cmp when NaN-aware total ordering is required.
Binary search assumes the slice is already sorted by the exact same ordering.
If duplicates exist, binary_search may return any matching index.
Use partition_point to find lower and upper bounds around duplicate runs.
The insertion index from Err(i) is where a value could be inserted while preserving sorted order.
Do not sort just to find one item unless repeated searches justify the sort cost.
Example
fn main() {
let mut words = vec!["pear", "fig", "banana", "kiwi"];
words.sort_by_key(|word| word.len());
assert_eq!(words, vec!["fig", "pear", "kiwi", "banana"]);
let lengths: Vec<usize> = words.iter().map(|word| word.len()).collect();
assert!(matches!(lengths.binary_search(&4), Ok(1 | 2)));
assert_eq!(lengths.binary_search(&5), Err(3));
let first_len_four = lengths.partition_point(|len| *len < 4);
let after_len_four = lengths.partition_point(|len| *len <= 4);
assert_eq!(&words[first_len_four..after_len_four], &["pear", "kiwi"]);
}Best practice
- ✅ Sort with
sortwhen equal-element order matters. - ✅ Sort with
sort_unstablewhen equal-element order does not matter. - ✅ Use
sort_by_keyfor cheap derived keys. - ✅ Use
sort_by_cached_keyfor expensive key extraction. - ✅ Use
binary_search_by_keywhen searching by one field of a struct. - ✅ Use the
Errinsertion index to maintain sorted vectors. - ✅ Use
partition_pointfor duplicate ranges and insertion positions. - ✅ Keep comparator logic small and test it when domain ordering is subtle.
Pitfalls
- ⚠️ Binary search on an unsorted slice returns meaningless results.
- ⚠️ Sorting by one key and searching by another violates the search precondition.
- ⚠️
binary_searchdoes not guarantee the first matching duplicate. - ⚠️ A comparator that is not transitive can make sorting panic or produce surprising order.
- ⚠️
partial_cmp(...).unwrap()on floats can panic on NaN. - ⚠️
sort_by_keyrecomputes keys during sorting; use cached keys when key extraction is expensive. - ⚠️ Inserting into the middle of a
Vecafter search is O(n) because later elements shift. - ⚠️ Sorting invalidates assumptions tied to old indexes.
See also
std: Vec, String & Slices · Vec Methods Reference · The Slice Type · Slicing and Range Indexing · Index Panics vs get · Iterator Performance · PartialEq · Stale Slice Indices · Manual Index Loops for Speed
Sources
- Rust standard library, slice sorting methods — std, https://doc.rust-lang.org/std/primitive.slice.html#method.sort
- Rust standard library, slice binary search methods — std, https://doc.rust-lang.org/std/primitive.slice.html#method.binary_search
