Skip to content

Commit

Permalink
std::vec: add a sugary .sort() method for plain Ord sorting.
Browse files Browse the repository at this point in the history
This moves the custom sorting to `.sort_by`.
  • Loading branch information
huonw committed Dec 20, 2013
1 parent 48fedcb commit 1b1e4ca
Show file tree
Hide file tree
Showing 16 changed files with 91 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/libextra/glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl Iterator<Path> for GlobIterator {
fn list_dir_sorted(path: &Path) -> ~[Path] {
match io::result(|| fs::readdir(path)) {
Ok(mut children) => {
children.sort(|p1, p2| p2.filename() <= p1.filename());
children.sort_by(|p1, p2| p2.filename() <= p1.filename());
children
}
Err(..) => ~[]
Expand Down
8 changes: 6 additions & 2 deletions src/libextra/priority_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,11 @@ mod tests {
fn test_top_and_pop() {
let data = ~[2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
let mut sorted = data.clone();
<<<<<<< HEAD
sorted.sort(|x, y| x.le(y));
=======
sorted.sort();
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
let mut heap = PriorityQueue::from_vec(data);
while !heap.is_empty() {
assert_eq!(heap.top(), sorted.last());
Expand Down Expand Up @@ -314,8 +318,8 @@ mod tests {
fn check_to_vec(mut data: ~[int]) {
let heap = PriorityQueue::from_vec(data.clone());
let mut v = heap.clone().to_vec();
v.sort(|x, y| x.le(y));
data.sort(|x, y| x.le(y));
v.sort();
data.sort();

assert_eq!(v, data);
assert_eq!(heap.to_sorted_vec(), data);
Expand Down
6 changes: 3 additions & 3 deletions src/libextra/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,13 @@ impl<'a> Stats for &'a [f64] {

fn percentile(self, pct: f64) -> f64 {
let mut tmp = self.to_owned();
tmp.sort(|a,b| a <= b);
tmp.sort();
percentile_of_sorted(tmp, pct)
}

fn quartiles(self) -> (f64,f64,f64) {
let mut tmp = self.to_owned();
tmp.sort(|a,b| a <= b);
tmp.sort();
let a = percentile_of_sorted(tmp, 25.0);
let b = percentile_of_sorted(tmp, 50.0);
let c = percentile_of_sorted(tmp, 75.0);
Expand Down Expand Up @@ -290,7 +290,7 @@ fn percentile_of_sorted(sorted_samples: &[f64],
/// See: http://en.wikipedia.org/wiki/Winsorising
pub fn winsorize(samples: &mut [f64], pct: f64) {
let mut tmp = samples.to_owned();
tmp.sort(|a,b| a <= b);
tmp.sort();
let lo = percentile_of_sorted(tmp, pct);
let hi = percentile_of_sorted(tmp, 100.0-pct);
for samp in samples.mut_iter() {
Expand Down
5 changes: 2 additions & 3 deletions src/libextra/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ use std::to_str::ToStr;
use std::f64;
use std::os;


// The name of a test. By convention this follows the rules for rust
// paths; i.e. it should be a series of identifiers separated by double
// colons. This way if some test runner wants to arrange the tests
Expand Down Expand Up @@ -487,7 +486,7 @@ impl<T: Writer> ConsoleTestState<T> {
for f in self.failures.iter() {
failures.push(f.name.to_str());
}
failures.sort(|a,b| a <= b);
failures.sort();
for name in failures.iter() {
self.write_plain(format!(" {}\n", name.to_str()));
}
Expand Down Expand Up @@ -841,7 +840,7 @@ pub fn filter_tests(
fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool {
t1.desc.name.to_str() <= t2.desc.name.to_str()
}
filtered.sort(lteq);
filtered.sort_by(lteq);

// Shard the remaining tests, if sharding requested.
match opts.test_shard {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Available lint options:
let mut lint_dict = lint_dict.move_iter()
.map(|(k, v)| (v, k))
.collect::<~[(lint::LintSpec, &'static str)]>();
lint_dict.sort(|a,b| a <= b);
lint_dict.sort();

let mut max_key = 0;
for &(_, name) in lint_dict.iter() {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ pub fn get_dep_hashes(cstore: &CStore) -> ~[@str] {
});
}

result.sort(|a, b| (a.name, a.vers, a.hash) <= (b.name, b.vers, b.hash));
result.sort();

debug!("sorted:");
for x in result.iter() {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1531,7 +1531,7 @@ fn encode_crate_deps(ecx: &EncodeContext,
});

// Sort by cnum
deps.sort(|kv1, kv2| kv1.cnum <= kv2.cnum);
deps.sort_by(|kv1, kv2| kv1.cnum <= kv2.cnum);

// Sanity-check the crate numbers
let mut expected_cnum = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ fn missing_ctor(cx: &MatchCheckCtxt,

// Sort them by length such that for patterns of the same length,
// those with a destructured slice come first.
vec_pat_lens.sort(|&(len1, slice1), &(len2, slice2)| {
vec_pat_lens.sort_by(|&(len1, slice1), &(len2, slice2)| {
if len1 == len2 {
slice1 > slice2
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3163,7 +3163,7 @@ pub fn trans_crate(sess: session::Session,
println!("n_closures: {}", ccx.stats.n_closures);
println("fn stats:");

ccx.stats.fn_stats.sort(|&(_, _, insns_a), &(_, _, insns_b)| insns_a >= insns_b);
ccx.stats.fn_stats.sort_by(|&(_, _, insns_a), &(_, _, insns_b)| insns_a >= insns_b);

for tuple in ccx.stats.fn_stats.iter() {
match *tuple {
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ fn item_module(w: &mut Writer, cx: &Context,
}

debug!("{:?}", indices);
indices.sort(|&i1, &i2| le(&items[i1], &items[i2], i1, i2));
indices.sort_by(|&i1, &i2| le(&items[i1], &items[i2], i1, i2));

debug!("{:?}", indices);
let mut curty = "";
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
pub use vec::{ImmutableEqVector, ImmutableTotalOrdVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector, MutableVector};
pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector, MutableVector, MutableOrdVector};
pub use vec::{Vector, VectorVector, CopyableVector, ImmutableVector};

// Reexported runtime types
Expand Down
69 changes: 63 additions & 6 deletions src/libstd/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2181,7 +2181,7 @@ pub trait MutableVector<'a, T> {
/// v.sort(|a, b| *b <= *a);
/// assert_eq!(v, [5, 4, 3, 2, 1]);
/// ```
fn sort(self, less_eq: |&T, &T| -> bool);
fn sort_by(self, less_eq: |&T, &T| -> bool);

/**
* Consumes `src` and moves as many elements as it can into `self`
Expand Down Expand Up @@ -2328,7 +2328,11 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
}

#[inline]
<<<<<<< HEAD
fn sort(self, less_eq: |&T, &T| -> bool) {
=======
fn sort_by<Sort: SortComparator<T>>(self, less_eq: Sort) {
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
merge_sort(self, less_eq)
}

Expand Down Expand Up @@ -2385,6 +2389,32 @@ impl<'a, T:Clone> MutableCloneableVector<T> for &'a mut [T] {
}
}

/// Methods for mutable vectors with orderable elements, such as
/// in-place sorting.
pub trait MutableOrdVector<T> {
/// Sort the vector, in place.
///
/// This is equivalent to `self.sort_by(std::vec::SortForward)`.
///
/// # Example
///
/// ```rust
/// use std::vec;
///
/// let mut v = [-5, 4, 1, -3, 2];
///
/// v.sort();
/// assert_eq!(v, [-5, -3, 1, 2, 4]);
/// ```
fn sort(self);
}
impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
#[inline]
fn sort(self) {
self.sort_by(SortForward)
}
}

/**
* Constructs a vector from an unsafe pointer to a buffer
*
Expand Down Expand Up @@ -3474,16 +3504,39 @@ mod tests {
let mut v = task_rng().gen_vec::<uint>(len);
v.sort(|a,b| a <= b);

<<<<<<< HEAD
assert!(v.windows(2).all(|w| w[0] <= w[1]));
=======
let mut v1 = v.clone();
let mut v2 = v.clone();
v.sort();
assert!(v.windows(2).all(|w| w[0] <= w[1]));

v1.sort_by(vec::SortForward);
assert!(v1.windows(2).all(|w| w[0] <= w[1]));

v1.sort_by(vec::SortReverse);
assert!(v1.windows(2).all(|w| w[0] >= w[1]));

v2.sort_by(|a: &uint, b: &uint| a <= b);
assert!(v2.windows(2).all(|w| w[0] <= w[1]));
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
}
}

// shouldn't fail/crash
let mut v: [uint, .. 0] = [];
<<<<<<< HEAD
v.sort(|a,b| a <= b);

let mut v = [0xDEADBEEF];
v.sort(|a,b| a <= b);
=======
v.sort_by(SortForward);

let mut v = [0xDEADBEEF];
v.sort_by(SortForward);
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
assert_eq!(v, [0xDEADBEEF]);
}

Expand All @@ -3506,7 +3559,11 @@ mod tests {

// only sort on the first element, so an unstable sort
// may mix up the counts.
<<<<<<< HEAD
v.sort(|&(a,_), &(b,_)| a <= b);
=======
v.sort_by(|&(a,_): &(uint, uint), &(b,_): &(uint, uint)| a <= b);
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.

// this comparison includes the count (the second item
// of the tuple), so elements with equal first items
Expand Down Expand Up @@ -4341,7 +4398,7 @@ mod bench {
use extra::test::BenchHarness;
use iter::range;
use vec;
use vec::VectorVector;
use vec::{VectorVector, MutableOrdVector};
use option::*;
use ptr;
use rand::{weak_rng, task_rng, Rng};
Expand Down Expand Up @@ -4551,7 +4608,7 @@ mod bench {
let mut rng = weak_rng();
bh.iter(|| {
let mut v: ~[f64] = rng.gen_vec(5);
v.sort(|a,b| *a <= *b);
v.sort();
});
bh.bytes = 5 * mem::size_of::<f64>() as u64;
}
Expand All @@ -4561,7 +4618,7 @@ mod bench {
let mut rng = weak_rng();
bh.iter(|| {
let mut v: ~[f64] = rng.gen_vec(100);
v.sort(|a,b| *a <= *b);
v.sort();
});
bh.bytes = 100 * mem::size_of::<f64>() as u64;
}
Expand All @@ -4571,7 +4628,7 @@ mod bench {
let mut rng = weak_rng();
bh.iter(|| {
let mut v: ~[f64] = rng.gen_vec(10000);
v.sort(|a,b| *a <= *b);
v.sort();
});
bh.bytes = 10000 * mem::size_of::<f64>() as u64;
}
Expand All @@ -4580,7 +4637,7 @@ mod bench {
fn sort_sorted(bh: &mut BenchHarness) {
let mut v = vec::from_fn(10000, |i| i);
bh.iter(|| {
v.sort(|a,b| *a <= *b);
v.sort();
});
bh.bytes = (v.len() * mem::size_of_val(&v[0])) as u64;
}
Expand Down
4 changes: 4 additions & 0 deletions src/libsyntax/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,11 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> ~[@MetaItem] {
.map(|&mi| (mi.name(), mi))
.collect::<~[(@str, @MetaItem)]>();

<<<<<<< HEAD
v.sort(|&(a, _), &(b, _)| a <= b);
=======
v.sort_by(|&(a, _): &(@str, @MetaItem), &(b, _): &(@str, @MetaItem)| a <= b);
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.

// There doesn't seem to be a more optimal way to do this
v.move_iter().map(|(_, m)| {
Expand Down
4 changes: 2 additions & 2 deletions src/test/bench/shootout-k-nucleotide-pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {

// sort by key, then by value
fn sortKV<TT:Clone + Ord, UU:Clone + Ord>(mut orig: ~[(TT,UU)]) -> ~[(TT,UU)] {
orig.sort(le_by_key);
orig.sort(le_by_val);
orig.sort_by(le_by_key);
orig.sort_by(le_by_val);
origin
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/bench/shootout-k-nucleotide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ fn print_frequencies(frequencies: &Table, frame: i32) {
for frequencies.each |entry| {
vector.push((entry.code, entry.count));
}
vector.sort(|a,b| a <= b);
vector.sort();

let mut total_count = 0;
for vector.each |&(_, count)| {
Expand Down
4 changes: 2 additions & 2 deletions src/test/run-pass/vector-sort-failure-safe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn main() {
// work out the total number of comparisons required to sort
// this array...
let mut count = 0;
main.clone().sort(|a, b| { count += 1; a <= b });
main.clone().sort_by(|a, b| { count += 1; a <= b });

// ... and then fail on each and every single one.
for fail_countdown in range(0, count) {
Expand All @@ -63,7 +63,7 @@ pub fn main() {
std::task::try(proc() {
let mut v = v;
let mut fail_countdown = fail_countdown;
v.sort(|a, b| {
v.sort_by(|a, b| {
if fail_countdown == 0 {
fail!()
}
Expand Down

0 comments on commit 1b1e4ca

Please sign in to comment.