Alphanumeric sort. When sorting strings that contain numeric parts, we may want to sort them by the values of those numbers. This is called an alphanumeric sorting algorithm.
In Rust we implement sorting methods by returning an Ordering enum. The comparison method must consume parts of strings and then compare them differently depending on whether they are numeric.
This Rust program performs some alphanumeric sorting on highway names that have leading letters and then numbers. It manages to consider "SR9" as earlier than "SR100".
Part 1 In our comparison method, we get vectors of chars for each string we are comparing for easier element access logic.
Part 3 The program builds up chunks of all digit or non-digit characters with some nested loops.
Part 4 This function, get_chunk_at, builds up a string of all digit or non-digit chars and returns it.
Part 5 The logic tests whether the chunks are composed of digits—if so, they are compared numerically. Otherwise they are treated as strings.
Part 6 In main() we build up an array of highway names, and then use the sort_by() method to sort the strings alphanumerically.
use std::cmp::*;
fn get_chunk_at(marker: &mut usize, chars: &Vec<char>) -> String {
// Part 4: while the characters are all digits (or not), build up a chunk.
let mut c = chars[*marker];
let mut str = String::new();
let first_digit = c.is_ascii_digit();
loop {
str.push(c);
*marker += 1;
if *marker < chars.len() {
c = chars[*marker];
} else {
break;
}
if c.is_ascii_digit() != first_digit {
break;
}
}
str
}
fn compare_alphanumeric(a: &String, b: &String) -> Ordering {
// Part 1: get char vectors for each string.
let chars1 = a.chars().collect::<Vec<char>>();
let chars2 = b.chars().collect::<Vec<char>>();
let mut marker1 = 0;
let mut marker2 = 0;
loop {
// Part 2: iterate through the vectors with 2 markers.
if marker1 >= chars1.len() || marker2 >= chars2.len() {
break;
}
// Part 3: collect all chars of digit type or not.
let str1 = get_chunk_at(&mut marker1, &chars1);
let str2 = get_chunk_at(&mut marker2, &chars2);
// Part 5: compare the 2 chunks based on integers or strings based on their contents.
if let Ok(chunk1) = str1.parse::<i32>() {
if let Ok(chunk2) = str2.parse::<i32>() {
if chunk1 != chunk2 {
return chunk1.cmp(&chunk2);
}
}
}
if str1 != str2 {
return str1.cmp(&str2);
}
}
chars1.len().cmp(&chars2.len())
}
fn main() {
// Part 6: use the alphanumeric sorting algorithm.
let mut highways = vec![
"100F".to_string(),
"50F".to_string(),
"SR100".to_string(),
"SR9".to_string(),
];
println!("{:?}", highways);
highways.sort_by(compare_alphanumeric);
println!("{:?}", highways);
}["100F", "50F", "SR100", "SR9"]
["50F", "100F", "SR9", "SR100"]
Though the method here could be improved in many ways, it seems to function correctly on the example data. Its performance could be improved as well as its reliability.
Dot Net Perls is a collection of pages with code examples, which are updated to stay current. Programming is an art, and it can be learned from examples.
Donate to this site to help offset the costs of running the server. Sites like this will cease to exist if there is no financial support for them.
Sam Allen is passionate about computer languages, and he maintains 100% of the material available on this website. He hopes it makes the world a nicer place.
This page was last updated on Mar 13, 2025 (new example).