Skip to content

Commit

Permalink
random option for sort command
Browse files Browse the repository at this point in the history
Though this overlaps with the new `scramble` command, it's still useful to adapt this PR.

BurntSushi/xsv#185
  • Loading branch information
jqnatividad committed Nov 5, 2021
1 parent b5f1cfc commit 0cdb5a1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 45 deletions.
70 changes: 32 additions & 38 deletions src/cmd/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::config::{Config, Delimiter};
use crate::select::SelectColumns;
use crate::util;
use crate::CliResult;
use rand::{seq::SliceRandom, SeedableRng, rngs::StdRng};
use serde::Deserialize;
use rand::{thread_rng, Rng, SeedableRng, StdRng};
use std::str::from_utf8;

use self::Number::{Float, Int};
Expand Down Expand Up @@ -46,7 +46,7 @@ struct Args {
flag_numeric: bool,
flag_reverse: bool,
flag_random: bool,
flag_seed: Option<usize>,
flag_seed: Option<u64>,
flag_output: Option<String>,
flag_no_headers: bool,
flag_delimiter: Option<Delimiter>,
Expand All @@ -70,45 +70,39 @@ pub fn run(argv: &[&str]) -> CliResult<()> {

// Seeding rng
let seed = args.flag_seed;
let mut rng: StdRng = match seed {
None => {
StdRng::from_rng(thread_rng()).unwrap()
}
Some(seed) => {
let mut buf = [0u8; 32];
LittleEndian::write_u64(&mut buf, seed as u64);
SeedableRng::from_seed(buf)
}
};

let mut all = rdr.byte_records().collect::<Result<Vec<_>, _>>()?;
match (numeric, reverse, random) {
(_, _, true) =>
rng.shuffle(&mut all),
(false, false, false) =>
all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp(a, b)
}),
(true, false, false) =>
all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp_num(a, b)
}),
(false, true, false) =>
all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp(b, a)
}),
(true, true, false) =>
all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp_num(b, a)
}),
(_, _, true) => {
//SliceRandom::shuffle(&mut all, &mut rng),
if let Some(val) = seed {
let mut rng = StdRng::seed_from_u64(val);
SliceRandom::shuffle(&mut *all, &mut rng);
} else {
let mut rng = ::rand::thread_rng();
SliceRandom::shuffle(&mut *all, &mut rng);
}
}
(false, false, false) => all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp(a, b)
}),
(true, false, false) => all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp_num(a, b)
}),
(false, true, false) => all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp(b, a)
}),
(true, true, false) => all.sort_by(|r1, r2| {
let a = sel.select(r1);
let b = sel.select(r2);
iter_cmp_num(b, a)
}),
}

let mut wtr = Config::new(&args.flag_output).writer()?;
Expand Down
25 changes: 18 additions & 7 deletions tests/test_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,31 @@ fn sort_uniq() {
#[test]
fn sort_random() {
let wrk = Workdir::new("sort_random");
wrk.create("in.csv", vec![
svec!["R", "S"],
svec!["1", "b"],
svec!["2", "a"],
]);
wrk.create(
"in.csv",
vec![
svec!["R", "S"],
svec!["1", "b"],
svec!["2", "a"],
svec!["3", "d"],
svec!["4", "c"],
svec!["5", "f"],
svec!["6", "e"],
],
);

let mut cmd = wrk.command("sort");
cmd.arg("--random").args(&["--seed", "0"]).arg("in.csv");
cmd.arg("--random").args(&["--seed", "42"]).arg("in.csv");

let got: Vec<Vec<String>> = wrk.read_stdout(&mut cmd);
let expected = vec![
svec!["R", "S"],
svec!["2", "a"],
svec!["1", "b"],
svec!["5", "f"],
svec!["6", "e"],
svec!["3", "d"],
svec!["2", "a"],
svec!["4", "c"],
];
assert_eq!(got, expected);
}
Expand Down

0 comments on commit 0cdb5a1

Please sign in to comment.