exa/sort.rs
2014-06-01 11:54:31 +01:00

50 lines
1.5 KiB
Rust

// This is an implementation of "natural sort order". See
// http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
// for more information and examples. It tries to sort "9" before
// "10", which makes sense to those regular human types.
// It works by splitting an input string into several parts, and then
// comparing based on those parts. A SortPart derives TotalOrd, so a
// Vec<SortPart> will automatically have natural sorting.
#[deriving(Eq, Ord, TotalEq, TotalOrd)]
pub enum SortPart<'a> {
Stringular(&'a str),
Numeric(u32),
}
impl<'a> SortPart<'a> {
pub fn from_string(is_digit: bool, slice: &'a str) -> SortPart<'a> {
if is_digit {
Numeric(from_str::<u32>(slice).unwrap())
} else {
Stringular(slice)
}
}
// The logic here is taken from my question at
// http://stackoverflow.com/q/23969191/3484614
pub fn split_into_parts<'a>(input: &'a str) -> Vec<SortPart<'a>> {
let mut parts = vec![];
if input.is_empty() {
return parts
}
let mut is_digit = input.char_at(0).is_digit();
let mut start = 0;
for (i, c) in input.char_indices() {
if is_digit != c.is_digit() {
parts.push(SortPart::from_string(is_digit, input.slice(start, i)));
is_digit = !is_digit;
start = i;
}
}
parts.push(SortPart::from_string(is_digit, input.slice_from(start)));
parts
}
}