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".
string
we are comparing for easier element access logic.get_chunk_at
, builds up a string
of all digit or non-digit chars and returns it.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.