1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Merge pull request #932 from alsuren/sort--stable

implement sort --stable
This commit is contained in:
Nathan Ross 2016-08-03 06:52:39 -04:00 committed by GitHub
commit 63c17e5b42
6 changed files with 66 additions and 6 deletions

View file

@ -43,6 +43,7 @@ struct Settings {
mode: SortMode, mode: SortMode,
reverse: bool, reverse: bool,
outfile: Option<String>, outfile: Option<String>,
stable: bool,
unique: bool, unique: bool,
check: bool, check: bool,
} }
@ -53,6 +54,7 @@ impl Default for Settings {
mode: SortMode::Default, mode: SortMode::Default,
reverse: false, reverse: false,
outfile: None, outfile: None,
stable: false,
unique: false, unique: false,
check: false, check: false,
} }
@ -70,6 +72,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
opts.optflag("h", "help", "display this help and exit"); opts.optflag("h", "help", "display this help and exit");
opts.optflag("", "version", "output version information and exit"); opts.optflag("", "version", "output version information and exit");
opts.optopt("o", "output", "write output to FILENAME instead of stdout", "FILENAME"); opts.optopt("o", "output", "write output to FILENAME instead of stdout", "FILENAME");
opts.optflag("s", "stable", "stabilize sort by disabling last-resort comparison");
opts.optflag("u", "unique", "output only the first of an equal run"); opts.optflag("u", "unique", "output only the first of an equal run");
opts.optflag("V", "version-sort", "Sort by SemVer version number, eg 1.12.2 > 1.1.2"); opts.optflag("V", "version-sort", "Sort by SemVer version number, eg 1.12.2 > 1.1.2");
opts.optflag("c", "check", "check for sorted input; do not sort"); opts.optflag("c", "check", "check for sorted input; do not sort");
@ -112,6 +115,7 @@ With no FILE, or when FILE is -, read standard input.", NAME, VERSION);
settings.reverse = matches.opt_present("reverse"); settings.reverse = matches.opt_present("reverse");
settings.outfile = matches.opt_str("output"); settings.outfile = matches.opt_str("output");
settings.stable = matches.opt_present("stable");
settings.unique = matches.opt_present("unique"); settings.unique = matches.opt_present("unique");
settings.check = matches.opt_present("check"); settings.check = matches.opt_present("check");
@ -146,14 +150,25 @@ fn exec(files: Vec<String>, settings: &Settings) -> i32 {
let original_lines = lines.to_vec(); let original_lines = lines.to_vec();
match settings.mode { let mut compare_fns = Vec::new();
SortMode::Numeric => lines.sort_by(numeric_compare),
SortMode::HumanNumeric => lines.sort_by(human_numeric_size_compare), compare_fns.push(match settings.mode {
SortMode::Month => lines.sort_by(month_compare), SortMode::Numeric => numeric_compare,
SortMode::Version => lines.sort_by(version_compare), SortMode::HumanNumeric => human_numeric_size_compare,
SortMode::Default => lines.sort() SortMode::Month => month_compare,
SortMode::Version => version_compare,
SortMode::Default => String::cmp
});
if !settings.stable {
match settings.mode {
SortMode::Default => {}
_ => compare_fns.push(String::cmp)
}
} }
sort_by(&mut lines, compare_fns);
if settings.unique { if settings.unique {
lines.dedup() lines.dedup()
} }
@ -178,6 +193,20 @@ fn exec(files: Vec<String>, settings: &Settings) -> i32 {
} }
fn sort_by<F>(lines: &mut Vec<String>, compare_fns: Vec<F>)
where F: Fn( &String, &String ) -> Ordering
{
lines.sort_by(|a, b| {
for compare_fn in &compare_fns {
let cmp = compare_fn(a, b);
if cmp != Ordering::Equal {
return cmp;
}
}
return Ordering::Equal;
})
}
/// Parse the beginning string into an f64, returning -inf instead of NaN on errors. /// Parse the beginning string into an f64, returning -inf instead of NaN on errors.
fn permissive_f64_parse(a: &str) -> f64 { fn permissive_f64_parse(a: &str) -> f64 {
// Maybe should be split on non-digit, but then 10e100 won't parse properly. // Maybe should be split on non-digit, but then 10e100 won't parse properly.

View file

@ -3,5 +3,8 @@ Jan Lorem ipsum dolor sit amet
mar laboris nisi ut aliquip ex ea mar laboris nisi ut aliquip ex ea
May sed do eiusmod tempor incididunt May sed do eiusmod tempor incididunt
JUN nostrud exercitation ullamco JUN nostrud exercitation ullamco
Jul 1 should remain 2,1,3
Jul 2 these three lines
Jul 3 if --stable is provided
Oct ut labore et dolore magna aliqua Oct ut labore et dolore magna aliqua
Dec consectetur adipiscing elit Dec consectetur adipiscing elit

View file

@ -5,3 +5,6 @@ Oct ut labore et dolore magna aliqua
N/A Ut enim ad minim veniam, quis N/A Ut enim ad minim veniam, quis
JUN nostrud exercitation ullamco JUN nostrud exercitation ullamco
mar laboris nisi ut aliquip ex ea mar laboris nisi ut aliquip ex ea
Jul 2 these three lines
Jul 1 should remain 2,1,3
Jul 3 if --stable is provided

View file

@ -0,0 +1,10 @@
N/A Ut enim ad minim veniam, quis
Jan Lorem ipsum dolor sit amet
mar laboris nisi ut aliquip ex ea
May sed do eiusmod tempor incididunt
JUN nostrud exercitation ullamco
Jul 2 these three lines
Jul 1 should remain 2,1,3
Jul 3 if --stable is provided
Oct ut labore et dolore magna aliqua
Dec consectetur adipiscing elit

10
tests/fixtures/sort/month_stable.txt vendored Normal file
View file

@ -0,0 +1,10 @@
Jan Lorem ipsum dolor sit amet
Dec consectetur adipiscing elit
May sed do eiusmod tempor incididunt
Oct ut labore et dolore magna aliqua
N/A Ut enim ad minim veniam, quis
JUN nostrud exercitation ullamco
mar laboris nisi ut aliquip ex ea
Jul 2 these three lines
Jul 1 should remain 2,1,3
Jul 3 if --stable is provided

View file

@ -41,6 +41,11 @@ fn test_month_default() {
test_helper("month_default", "-M"); test_helper("month_default", "-M");
} }
#[test]
fn test_month_stable() {
test_helper("month_stable", "-Ms");
}
#[test] #[test]
fn test_default_unsorted_ints() { fn test_default_unsorted_ints() {
test_helper("default_unsorted_ints", ""); test_helper("default_unsorted_ints", "");