From 61c2a48ed52265ebd4f7d43eb4d16de276f373b0 Mon Sep 17 00:00:00 2001 From: mpostma Date: Sun, 3 May 2020 11:52:29 +0200 Subject: [PATCH 1/3] adds retain on slices --- src/libcore/slice/mod.rs | 45 ++++++++++++++++++++++++++++++++++++++++ src/libcore/tests/lib.rs | 1 + 2 files changed, 46 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index dc395bcfba5cc..f405978cbc6f1 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2063,6 +2063,51 @@ impl [T] { self.partition_dedup_by(|a, b| key(a) == key(b)) } + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_retain)] + /// + /// let mut slice = [1, 2, 3, 4]; + /// let retained = slice.retain(|&x| x % 2 == 0); + /// assert_eq!(retained, [2, 4]); + /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// #![feature(slice_retain)] + /// + /// let mut slice = [1, 2, 3, 4, 5]; + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// let retained = slice.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(retained, [2, 3, 5]); + /// ``` + #[unstable(feature = "slice_retain", issue = "71831")] + #[must_use] + pub fn retain(&mut self, mut f: F) -> &mut Self + where + F: FnMut(&T) -> bool, + { + let len = self.len(); + let mut del = 0; + for i in 0..len { + if !f(&self[i]) { + del += 1; + } else if del > 0 { + self.swap(i - del, i); + } + } + self.split_at_mut(len - del).0 + } + /// Rotates the slice in-place such that the first `mid` elements of the /// slice move to the end while the last `self.len() - mid` elements move to /// the front. After calling `rotate_left`, the element previously at index diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index e7d36d327cd89..f5f475f7f56cf 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -43,6 +43,7 @@ #![feature(leading_trailing_ones)] #![feature(const_forget)] #![feature(option_unwrap_none)] +#![feature(slice_retain)] extern crate test; From b0ae04c47a0b711e42c980029efb5eb7a2bebfa6 Mon Sep 17 00:00:00 2001 From: mpostma Date: Sun, 3 May 2020 11:53:03 +0200 Subject: [PATCH 2/3] tests retain --- src/libcore/tests/slice.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 54a585415bce2..7db5b4270270a 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -1635,6 +1635,17 @@ fn test_slice_partition_dedup_partialeq() { assert_eq!(duplicates, [Foo(0, 5), Foo(1, 9)]); } +#[test] +fn test_slice_retain() { + let mut slice = [1, 2, 2, 3, 1, 4]; + let retained = slice.retain(|&x| x == 1); + assert_eq!(retained, &[1, 1]); + + let mut slice = [1, 2, 2, 3, 1, 4]; + let retained = slice.retain(|&x| x % 2 == 0); + assert_eq!(retained, &[2, 2, 4]); +} + #[test] fn test_copy_within() { // Start to end, with a RangeTo. From 580f72898a9a4c36ae5e85656aeef0cbe9c20756 Mon Sep 17 00:00:00 2001 From: mpostma Date: Sun, 3 May 2020 11:53:27 +0200 Subject: [PATCH 3/3] updates retain on vec --- src/liballoc/lib.rs | 1 + src/liballoc/vec.rs | 20 +++----------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index a2071844d5dac..7fe6d2c2c0b4e 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -125,6 +125,7 @@ #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(associated_type_bounds)] +#![feature(slice_retain)] // Allow testing this library diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index b4a9da847876d..51533f9821f3a 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1103,26 +1103,12 @@ impl Vec { /// assert_eq!(vec, [2, 3, 5]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn retain(&mut self, mut f: F) + pub fn retain(&mut self, f: F) where F: FnMut(&T) -> bool, { - let len = self.len(); - let mut del = 0; - { - let v = &mut **self; - - for i in 0..len { - if !f(&v[i]) { - del += 1; - } else if del > 0 { - v.swap(i - del, i); - } - } - } - if del > 0 { - self.truncate(len - del); - } + let retained_len = self.as_mut_slice().retain(f).len(); + self.truncate(retained_len); } /// Removes all but the first of consecutive elements in the vector that resolve to the same