diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2021-07-31 20:23:01 +0200 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2021-07-31 20:23:01 +0200 |
| commit | 0c3510f690760db93b540f46ad4716e8614ba775 (patch) | |
| tree | 5a91214c80e73c72e2b060ae08a073ce4428187b /cli/src/main.rs | |
| parent | 10d6b82be501f219eb35b1cd94e1f0d461e9e165 (diff) | |
| download | money-0c3510f690760db93b540f46ad4716e8614ba775.tar.gz | |
sort inner
Diffstat (limited to 'cli/src/main.rs')
| -rw-r--r-- | cli/src/main.rs | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/cli/src/main.rs b/cli/src/main.rs index c7b300b..22f0da2 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -27,8 +27,7 @@ enum Command { #[structopt(long)] account: String, - // #[structopt(long = "category", multiple = true, number_of_values = 1)] - // category: Vec<String>, + //TODO multiple #[structopt(long)] category: String, @@ -44,9 +43,8 @@ enum Command { }, #[structopt(setting = AppSettings::AllowLeadingHyphen)] Show { - //TODO multiple sorts (sort iequals with later sorts) - #[structopt(long)] - sort: Option<SortTarget>, + #[structopt(long, multiple = true, number_of_values = 1)] + sort: Vec<SortTarget>, filters: Vec<String>, }, @@ -140,11 +138,51 @@ fn main() { search = search.parse(filters.join(" ")); } let mut transactions = search.get(); - transactions.sort_by(|t1, t2| match sort { - Some(SortTarget::Amount) => t1.amount.cmp(&t2.amount), - Some(SortTarget::Date) | None => t1.date.cmp(&t2.date), - }); + 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 macro? dynamic dispatch? trait objects? + match (&sort[i-1], &sort[i]) { + (SortTarget::Amount, SortTarget::Date) + => inner_sort_by_key(&mut transactions, |t| t.amount, |t| t.date), + (SortTarget::Date, SortTarget::Amount) + => inner_sort_by_key(&mut transactions, |t| t.date, |t| t.amount), + _ => panic!(), + } + } + } println!("{}", Table::new(transactions).with(Style::psql())); } } } + +fn inner_sort_by_key<F, G, K, L, T>(v: &mut [T], mut outer_key: F, mut inner_key: G) +where F: FnMut(&T) -> K, + G: FnMut(&T) -> L, + K: Ord, + L: Ord, +{ + // Early out + if v.len() < 2 { + return; + } + + let mut lower = 0; // Lower bound of current equal range + let mut last_k = outer_key(&v[0]); // Current key + for i in 0..v.len() { + let i_k = outer_key(&v[i]); + if i_k != last_k { + let upper = i; + if upper - lower > 1 { + v[lower..upper].sort_by_key(&mut inner_key); + } + lower = i; + last_k = i_k; + } + } +} |
