From 765402351c13ab0c2e6a1b2b52df3be0be0f34d7 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 10 Aug 2020 17:04:59 -0700 Subject: [PATCH] [breaking change] Reverse `drain_filter` behavior to match libstd Fixes #186. --- CHANGELOG.md | 5 +++++ src/map.rs | 24 +++++++++++++++--------- src/set.rs | 20 +++++++++++++------- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f95632d23b..081abc34f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed +- `drain_filter` now removes and yields items that do match the predicate, + rather than items that don't. This is a **breaking change** to match the + behavior of the `drain_filter` methods in `std`. + ## [v0.8.2] - 2020-08-08 ### Changed diff --git a/src/map.rs b/src/map.rs index 5ac8528c72..245b1d9d1f 100644 --- a/src/map.rs +++ b/src/map.rs @@ -584,13 +584,13 @@ impl HashMap { } } - /// Drains elements which are false under the given predicate, + /// Drains elements which are true under the given predicate, /// and returns an iterator over the removed items. /// - /// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `false` out + /// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `true` out /// into another iterator. /// - /// When the returned DrainedFilter is dropped, the elements that don't satisfy + /// When the returned DrainedFilter is dropped, any remaining elements that satisfy /// the predicate are dropped from the table. /// /// # Examples @@ -598,10 +598,16 @@ impl HashMap { /// ``` /// use hashbrown::HashMap; /// - /// let mut map: HashMap = (0..8).map(|x|(x, x*10)).collect(); - /// let drained = map.drain_filter(|&k, _| k % 2 == 0); - /// assert_eq!(drained.count(), 4); - /// assert_eq!(map.len(), 4); + /// let mut map: HashMap = (0..8).map(|x| (x, x)).collect(); + /// let drained: HashMap = map.drain_filter(|k, _v| k % 2 == 0).collect(); + /// + /// let mut evens = drained.keys().cloned().collect::>(); + /// let mut odds = map.keys().cloned().collect::>(); + /// evens.sort(); + /// odds.sort(); + /// + /// assert_eq!(evens, vec![0, 2, 4, 6]); + /// assert_eq!(odds, vec![1, 3, 5, 7]); /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn drain_filter(&mut self, f: F) -> DrainFilter<'_, K, V, F> @@ -1401,7 +1407,7 @@ impl DrainFilterInner<'_, K, V> { unsafe { while let Some(item) = self.iter.next() { let &mut (ref key, ref mut value) = item.as_mut(); - if !f(key, value) { + if f(key, value) { return Some(self.table.remove(item)); } } @@ -3763,7 +3769,7 @@ mod test_map { let drained = map.drain_filter(|&k, _| k % 2 == 0); let mut out = drained.collect::>(); out.sort_unstable(); - assert_eq!(vec![(1, 10), (3, 30), (5, 50), (7, 70)], out); + assert_eq!(vec![(0, 0), (2, 20), (4, 40), (6, 60)], out); assert_eq!(map.len(), 4); } { diff --git a/src/set.rs b/src/set.rs index a101225f12..21cfeb90bd 100644 --- a/src/set.rs +++ b/src/set.rs @@ -352,13 +352,13 @@ impl HashSet { self.map.retain(|k, _| f(k)); } - /// Drains elements which are false under the given predicate, + /// Drains elements which are true under the given predicate, /// and returns an iterator over the removed items. /// - /// In other words, move all elements `e` such that `f(&e)` returns `false` out + /// In other words, move all elements `e` such that `f(&e)` returns `true` out /// into another iterator. /// - /// When the returned DrainedFilter is dropped, the elements that don't satisfy + /// When the returned DrainedFilter is dropped, any remaining elements that satisfy /// the predicate are dropped from the set. /// /// # Examples @@ -367,9 +367,15 @@ impl HashSet { /// use hashbrown::HashSet; /// /// let mut set: HashSet = (0..8).collect(); - /// let drained = set.drain_filter(|&k| k % 2 == 0); - /// assert_eq!(drained.count(), 4); - /// assert_eq!(set.len(), 4); + /// let drained: HashSet = set.drain_filter(|v| v % 2 == 0).collect(); + /// + /// let mut evens = drained.into_iter().collect::>(); + /// let mut odds = set.into_iter().collect::>(); + /// evens.sort(); + /// odds.sort(); + /// + /// assert_eq!(evens, vec![0, 2, 4, 6]); + /// assert_eq!(odds, vec![1, 3, 5, 7]); /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn drain_filter(&mut self, f: F) -> DrainFilter<'_, T, F> @@ -2074,7 +2080,7 @@ mod test_set { let drained = set.drain_filter(|&k| k % 2 == 0); let mut out = drained.collect::>(); out.sort_unstable(); - assert_eq!(vec![1, 3, 5, 7], out); + assert_eq!(vec![0, 2, 4, 6], out); assert_eq!(set.len(), 4); } {