]> git.lizzy.rs Git - rust.git/commitdiff
Add Vec::dedup_by and Vec::dedup_by_key
authorSimon Sapin <simon.sapin@exyr.org>
Mon, 26 Sep 2016 16:26:49 +0000 (18:26 +0200)
committerSimon Sapin <simon.sapin@exyr.org>
Tue, 11 Oct 2016 12:39:14 +0000 (14:39 +0200)
src/libcollections/vec.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/vec.rs

index f8b4a92df2c5dca5dc25317e7fc6ac23d8a9fb8e..efbabb5a6f4ea0a48ea85aee68419da4174386ba 100644 (file)
@@ -1156,7 +1156,52 @@ impl<T: PartialEq> Vec<T> {
     /// assert_eq!(vec, [1, 2, 3, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn dedup(&mut self) {
+        self.dedup_by(|a, b| a == b)
+    }
+}
+
+impl<T> Vec<T> {
+    /// Removes consecutive elements in the vector that resolve to the same key.
+    ///
+    /// If the vector is sorted, this removes all duplicates.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(dedup_by)]
+    ///
+    /// let mut vec = vec![10, 20, 21, 30, 20];
+    ///
+    /// vec.dedup_by_key(|i| *i / 10);
+    ///
+    /// assert_eq!(vec, [10, 20, 30, 20]);
+    /// ```
+    #[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
+    #[inline]
+    pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
+        self.dedup_by(|a, b| key(a) == key(b))
+    }
+
+    /// Removes consecutive elements in the vector that resolve to the same key.
+    ///
+    /// If the vector is sorted, this removes all duplicates.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(dedup_by)]
+    /// use std::ascii::AsciiExt;
+    ///
+    /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
+    ///
+    /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
+    ///
+    /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
+    /// ```
+    #[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
+    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 `PartialEq` comparisons could panic, so we
@@ -1228,7 +1273,7 @@ pub fn dedup(&mut self) {
             while r < ln {
                 let p_r = p.offset(r as isize);
                 let p_wm1 = p.offset((w - 1) as isize);
-                if *p_r != *p_wm1 {
+                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);
index 878581a4f296ea304277860973c041b6c2076811..d6bad46c44dfb583c0ba5de414638bb02694b27e 100644 (file)
@@ -16,6 +16,7 @@
 #![feature(collections)]
 #![feature(collections_bound)]
 #![feature(const_fn)]
+#![feature(dedup_by)]
 #![feature(enumset)]
 #![feature(pattern)]
 #![feature(rand)]
index 1f4ab7f51a2c7330f5b8604fea91b4af7cd21a66..8417be289eb9eaf5e44826ba4635a66ca9179e2e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::iter::{FromIterator, repeat};
 use std::mem::size_of;
@@ -230,6 +231,31 @@ fn case(a: Vec<i32>, b: Vec<i32>) {
     case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
 }
 
+#[test]
+fn test_dedup_by_key() {
+    fn case(a: Vec<i32>, b: Vec<i32>) {
+        let mut v = a;
+        v.dedup_by_key(|i| *i / 10);
+        assert_eq!(v, b);
+    }
+    case(vec![], vec![]);
+    case(vec![10], vec![10]);
+    case(vec![10, 11], vec![10]);
+    case(vec![10, 20, 30], vec![10, 20, 30]);
+    case(vec![10, 11, 20, 30], vec![10, 20, 30]);
+    case(vec![10, 20, 21, 30], vec![10, 20, 30]);
+    case(vec![10, 20, 30, 31], vec![10, 20, 30]);
+    case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
+}
+
+#[test]
+fn test_dedup_by() {
+    let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
+    vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
+
+    assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
+}
+
 #[test]
 fn test_dedup_unique() {
     let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];