Make the Vec::dedup
method use slice::partition_dedup
internally
This commit is contained in:
parent
78bccb3540
commit
d560292a87
2 changed files with 7 additions and 84 deletions
|
@ -119,6 +119,7 @@
|
||||||
#![feature(exact_chunks)]
|
#![feature(exact_chunks)]
|
||||||
#![feature(rustc_const_unstable)]
|
#![feature(rustc_const_unstable)]
|
||||||
#![feature(const_vec_new)]
|
#![feature(const_vec_new)]
|
||||||
|
#![feature(slice_partition_dedup)]
|
||||||
#![feature(maybe_uninit)]
|
#![feature(maybe_uninit)]
|
||||||
|
|
||||||
// Allow testing this library
|
// Allow testing this library
|
||||||
|
|
|
@ -963,90 +963,12 @@ impl<T> Vec<T> {
|
||||||
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "dedup_by", since = "1.16.0")]
|
#[stable(feature = "dedup_by", since = "1.16.0")]
|
||||||
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
|
pub fn dedup_by<F>(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
|
||||||
unsafe {
|
let len = {
|
||||||
// Although we have a mutable reference to `self`, we cannot make
|
let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket);
|
||||||
// *arbitrary* changes. The `same_bucket` calls could panic, so we
|
dedup.len()
|
||||||
// must ensure that the vector is in a valid state at all time.
|
};
|
||||||
//
|
self.truncate(len);
|
||||||
// The way that we handle this is by using swaps; we iterate
|
|
||||||
// over all the elements, swapping as we go so that at the end
|
|
||||||
// the elements we wish to keep are in the front, and those we
|
|
||||||
// wish to reject are at the back. We can then truncate the
|
|
||||||
// vector. This operation is still O(n).
|
|
||||||
//
|
|
||||||
// Example: We start in this state, where `r` represents "next
|
|
||||||
// read" and `w` represents "next_write`.
|
|
||||||
//
|
|
||||||
// r
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// | 0 | 1 | 1 | 2 | 3 | 3 |
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// w
|
|
||||||
//
|
|
||||||
// Comparing self[r] against self[w-1], this is not a duplicate, so
|
|
||||||
// we swap self[r] and self[w] (no effect as r==w) and then increment both
|
|
||||||
// r and w, leaving us with:
|
|
||||||
//
|
|
||||||
// r
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// | 0 | 1 | 1 | 2 | 3 | 3 |
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// w
|
|
||||||
//
|
|
||||||
// Comparing self[r] against self[w-1], this value is a duplicate,
|
|
||||||
// so we increment `r` but leave everything else unchanged:
|
|
||||||
//
|
|
||||||
// r
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// | 0 | 1 | 1 | 2 | 3 | 3 |
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// w
|
|
||||||
//
|
|
||||||
// Comparing self[r] against self[w-1], this is not a duplicate,
|
|
||||||
// so swap self[r] and self[w] and advance r and w:
|
|
||||||
//
|
|
||||||
// r
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// | 0 | 1 | 2 | 1 | 3 | 3 |
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// w
|
|
||||||
//
|
|
||||||
// Not a duplicate, repeat:
|
|
||||||
//
|
|
||||||
// r
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// | 0 | 1 | 2 | 3 | 1 | 3 |
|
|
||||||
// +---+---+---+---+---+---+
|
|
||||||
// w
|
|
||||||
//
|
|
||||||
// Duplicate, advance r. End of vec. Truncate to w.
|
|
||||||
|
|
||||||
let ln = self.len();
|
|
||||||
if ln <= 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid bounds checks by using raw pointers.
|
|
||||||
let p = self.as_mut_ptr();
|
|
||||||
let mut r: usize = 1;
|
|
||||||
let mut w: usize = 1;
|
|
||||||
|
|
||||||
while r < ln {
|
|
||||||
let p_r = p.add(r);
|
|
||||||
let p_wm1 = p.add(w - 1);
|
|
||||||
if !same_bucket(&mut *p_r, &mut *p_wm1) {
|
|
||||||
if r != w {
|
|
||||||
let p_w = p_wm1.offset(1);
|
|
||||||
mem::swap(&mut *p_r, &mut *p_w);
|
|
||||||
}
|
|
||||||
w += 1;
|
|
||||||
}
|
|
||||||
r += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.truncate(w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Appends an element to the back of a collection.
|
/// Appends an element to the back of a collection.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue