interface_rs/helper/
sort.rs1use std::cmp::Ordering;
2
3pub fn natural(a: &str, b: &str) -> Ordering {
14 let mut a_iter = a.chars().peekable();
15 let mut b_iter = b.chars().peekable();
16
17 loop {
18 match (a_iter.peek(), b_iter.peek()) {
19 (Some(a_c), Some(b_c)) => {
20 if a_c.is_digit(10) && b_c.is_digit(10) {
21 let mut a_num = String::new();
23 while let Some(c) = a_iter.peek() {
24 if c.is_digit(10) {
25 a_num.push(*c);
26 a_iter.next();
27 } else {
28 break;
29 }
30 }
31
32 let mut b_num = String::new();
33 while let Some(c) = b_iter.peek() {
34 if c.is_digit(10) {
35 b_num.push(*c);
36 b_iter.next();
37 } else {
38 break;
39 }
40 }
41
42 let a_int = a_num.parse::<u64>().unwrap();
43 let b_int = b_num.parse::<u64>().unwrap();
44
45 match a_int.cmp(&b_int) {
46 Ordering::Equal => continue,
47 other => return other,
48 }
49 } else {
50 match a_c.cmp(b_c) {
52 Ordering::Equal => {
53 a_iter.next();
54 b_iter.next();
55 continue;
56 }
57 other => return other,
58 }
59 }
60 }
61 (Some(_), None) => return Ordering::Greater,
62 (None, Some(_)) => return Ordering::Less,
63 (None, None) => return Ordering::Equal,
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_sort_natural() {
74 assert_eq!(natural("swp1", "swp2"), Ordering::Less);
75 assert_eq!(natural("swp10", "swp2"), Ordering::Greater);
76 assert_eq!(natural("swp10", "swp10"), Ordering::Equal);
77 assert_eq!(natural("swp100", "swp20"), Ordering::Greater);
78 assert_eq!(natural("swp2", "swp2"), Ordering::Equal);
79 assert_eq!(natural("swp10s1", "swp10s2"), Ordering::Less);
80 assert_eq!(natural("swp10", "swp9s1"), Ordering::Greater);
81 }
82}