diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2021-07-31 22:49:00 +0200 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2021-07-31 22:49:00 +0200 |
| commit | abce6f2ae0f5fa36ea2069e69a4a070156644ea1 (patch) | |
| tree | 9b48d7319b4e8937b8c8afbc59bae22c6a8426d5 | |
| parent | 7c6ab4f9be74389366c81610e8266402fee9b45f (diff) | |
| download | money-abce6f2ae0f5fa36ea2069e69a4a070156644ea1.tar.gz | |
recursive inner_sort_by
| -rw-r--r-- | cli/src/main.rs | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/cli/src/main.rs b/cli/src/main.rs index 12325e2..e405e48 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,5 +1,6 @@ use chrono::naive::NaiveDate; use rust_decimal::Decimal; +use std::cmp::Ordering; use std::path::PathBuf; use std::str::FromStr; use structopt::clap::AppSettings; @@ -141,46 +142,44 @@ fn main() { if sort.is_empty() { transactions.sort_by_key(|t| t.date); } else { - match &sort[0] { - SortTarget::Amount => transactions.sort_by_key(|t| t.amount), - SortTarget::Date => transactions.sort_by_key(|t| t.date), - } - for i in 1..sort.len() { - //TODO This won't work with 3+ sorts in case key 2 are equal across a key 1 - // border. We need to pass the earlier buckets for later sorts as well. - // `Vec<range>`? - inner_sort_by(&mut transactions, sort_by_func(&sort[i-1]), sort_by_func(&sort[i])); - } + let mut sorts: Vec<_> = sort.iter().map(sort_by_func).collect(); + inner_sort_by(&mut transactions, &mut sorts); } println!("{}", Table::new(transactions).with(Style::psql())); } } } -fn sort_by_func(sort: &SortTarget) -> impl FnMut(&&Transaction, &&Transaction) -> std::cmp::Ordering { +fn sort_by_func(sort: &SortTarget) -> impl FnMut(&&Transaction, &&Transaction) -> Ordering { match sort { SortTarget::Amount => |t1: &&Transaction, t2: &&Transaction| t1.amount.cmp(&t2.amount), SortTarget::Date => |t1: &&Transaction, t2: &&Transaction| t1.date.cmp(&t2.date), } } -fn inner_sort_by<T, F>(v: &mut [T], mut outer_cmp: F, mut inner_cmp: F) +fn inner_sort_by<T, F>(v: &mut [T], cmps: &mut [F]) where - F: FnMut(&T, &T) -> std::cmp::Ordering, + F: FnMut(&T, &T) -> Ordering, { // Early out - if v.len() < 2 { + if v.len() < 2 || cmps.is_empty() { return; } + v.sort_by(&mut cmps[0]); + + let mut ranges = Vec::new(); let mut lower = 0; // Lower bound of current equal range for i in 0..v.len() { - if outer_cmp(&v[i], &v[lower]) != std::cmp::Ordering::Equal { - let upper = i; - if upper - lower > 1 { - v[lower..upper].sort_by(&mut inner_cmp); - } + if cmps[0](&v[i], &v[lower]) != Ordering::Equal { + ranges.push(lower..i); lower = i; } } + + if cmps.len() != 1 { + for range in ranges { + inner_sort_by(&mut v[range], &mut cmps[1..]); + } + } } |
