/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
/// ```
#[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 {
- unsafe {
- // Although we have a mutable reference to `self`, we cannot make
- // *arbitrary* changes. The `same_bucket` calls could panic, so we
- // must ensure that the vector is in a valid state at all time.
- //
- // 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);
- }
+ pub fn dedup_by<F>(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
+ let len = {
+ let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket);
+ dedup.len()
+ };
+ self.truncate(len);
}
/// Appends an element to the back of a collection.