From 777941f80c5c289989524722e85b6853c0aa8667 Mon Sep 17 00:00:00 2001 From: Taylor Hogge Date: Wed, 29 Nov 2017 01:12:20 -0700 Subject: [PATCH 1/2] Add support for dedup, dedup_by, and dedup_by_key --- lib.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/lib.rs b/lib.rs index 3cfa797..cf0363e 100644 --- a/lib.rs +++ b/lib.rs @@ -91,6 +91,13 @@ pub trait VecLike: /// Append an element to the vector. fn push(&mut self, value: T); + /// Removes consecutive repeated elements. + fn dedup(&mut self) where T: PartialEq; + /// Removes consecutive repeated elements with a given equality relation. + fn dedup_by(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool; + /// Removes consecutive elements that resolve to the same key. + fn dedup_by_key(&mut self, key: F) where F: FnMut(&mut T) -> K, + K: PartialEq; } impl VecLike for Vec { @@ -98,6 +105,23 @@ impl VecLike for Vec { fn push(&mut self, value: T) { Vec::push(self, value); } + + fn dedup(&mut self) where T: PartialEq { + Vec::dedup(self); + } + + fn dedup_by(&mut self, same_bucket: F) + where F: FnMut(&mut T, &mut T) -> bool + { + Vec::dedup_by(self, same_bucket); + } + + fn dedup_by_key(&mut self, key: F) + where F: FnMut(&mut T) -> K, + K: PartialEq + { + Vec::dedup_by_key(self, key); + } } /// Trait to be implemented by a collection that can be extended from a slice @@ -650,6 +674,50 @@ impl SmallVec { } self.truncate(len - del); } + + /// Removes consecutive duplicate elements. + pub fn dedup(&mut self) where A::Item: PartialEq { + self.dedup_by(|a, b| a == b); + } + + /// Removes consecutive duplicate elements using the given equality relation. + pub fn dedup_by(&mut self, mut same_bucket: F) + where F: FnMut(&mut A::Item, &mut A::Item) -> bool + { + // See the implementation of Vec::dedup_by in the + // standard library for an explanation of this algorithm. + let len = self.len; + if len <= 1 { + return; + } + + let ptr = self.as_mut_ptr(); + let mut w: usize = 1; + + unsafe { + for r in 1..len { + let p_r = ptr.offset(r as isize); + let p_wm1 = ptr.offset((w - 1) as isize); + 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; + } + } + } + + self.truncate(w); + } + + /// Removes consecutive elements that map to the same key. + pub fn dedup_by_key(&mut self, mut key: F) + where F: FnMut(&mut A::Item) -> K, + K: PartialEq + { + self.dedup_by(|a, b| key(a) == key(b)); + } } impl SmallVec where A::Item: Copy { @@ -858,6 +926,23 @@ impl VecLike for SmallVec { fn push(&mut self, value: A::Item) { SmallVec::push(self, value); } + + fn dedup(&mut self) where A::Item: PartialEq { + SmallVec::dedup(self); + } + + fn dedup_by(&mut self, same_bucket: F) + where F: FnMut(&mut A::Item, &mut A::Item) -> bool + { + SmallVec::dedup_by(self, same_bucket); + } + + fn dedup_by_key(&mut self, key: F) + where F: FnMut(&mut A::Item) -> K, + K: PartialEq + { + SmallVec::dedup_by_key(self, key); + } } impl FromIterator for SmallVec { @@ -1683,6 +1768,25 @@ pub mod tests { assert_eq!(Rc::strong_count(&one), 1); } + #[test] + fn test_dedup() { + let mut dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 2, 3, 3]); + dupes.dedup(); + assert_eq!(&*dupes, &[1, 2, 3]); + + let mut empty: SmallVec<[i32; 5]> = SmallVec::new(); + empty.dedup(); + assert!(empty.is_empty()); + + let mut all_ones: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 1, 1, 1]); + all_ones.dedup(); + assert_eq!(all_ones.len(), 1); + + let mut no_dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 4, 5]); + no_dupes.dedup(); + assert_eq!(no_dupes.len(), 5); + } + #[cfg(feature = "std")] #[test] fn test_write() { From 76cbf08519e73fcdfcbf8e607f949fff47dd9545 Mon Sep 17 00:00:00 2001 From: Taylor Hogge Date: Wed, 29 Nov 2017 10:33:47 -0700 Subject: [PATCH 2/2] Remove dedup and friends from VecLike trait to avoid breaking changes. --- lib.rs | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/lib.rs b/lib.rs index cf0363e..0db0e39 100644 --- a/lib.rs +++ b/lib.rs @@ -91,13 +91,6 @@ pub trait VecLike: /// Append an element to the vector. fn push(&mut self, value: T); - /// Removes consecutive repeated elements. - fn dedup(&mut self) where T: PartialEq; - /// Removes consecutive repeated elements with a given equality relation. - fn dedup_by(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool; - /// Removes consecutive elements that resolve to the same key. - fn dedup_by_key(&mut self, key: F) where F: FnMut(&mut T) -> K, - K: PartialEq; } impl VecLike for Vec { @@ -105,23 +98,6 @@ impl VecLike for Vec { fn push(&mut self, value: T) { Vec::push(self, value); } - - fn dedup(&mut self) where T: PartialEq { - Vec::dedup(self); - } - - fn dedup_by(&mut self, same_bucket: F) - where F: FnMut(&mut T, &mut T) -> bool - { - Vec::dedup_by(self, same_bucket); - } - - fn dedup_by_key(&mut self, key: F) - where F: FnMut(&mut T) -> K, - K: PartialEq - { - Vec::dedup_by_key(self, key); - } } /// Trait to be implemented by a collection that can be extended from a slice @@ -926,23 +902,6 @@ impl VecLike for SmallVec { fn push(&mut self, value: A::Item) { SmallVec::push(self, value); } - - fn dedup(&mut self) where A::Item: PartialEq { - SmallVec::dedup(self); - } - - fn dedup_by(&mut self, same_bucket: F) - where F: FnMut(&mut A::Item, &mut A::Item) -> bool - { - SmallVec::dedup_by(self, same_bucket); - } - - fn dedup_by_key(&mut self, key: F) - where F: FnMut(&mut A::Item) -> K, - K: PartialEq - { - SmallVec::dedup_by_key(self, key); - } } impl FromIterator for SmallVec {