Skip to content

Commit

Permalink
[breaking change] Reverse drain_filter behavior to match libstd
Browse files Browse the repository at this point in the history
Fixes #186.
  • Loading branch information
mbrubeck committed Aug 12, 2020
1 parent 101c045 commit 7654023
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 16 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 15 additions & 9 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,24 +584,30 @@ impl<K, V, S> HashMap<K, V, S> {
}
}

/// 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
///
/// ```
/// use hashbrown::HashMap;
///
/// let mut map: HashMap<i32, i32> = (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<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect();
///
/// let mut evens = drained.keys().cloned().collect::<Vec<_>>();
/// let mut odds = map.keys().cloned().collect::<Vec<_>>();
/// 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<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F>
Expand Down Expand Up @@ -1401,7 +1407,7 @@ impl<K, V> 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));
}
}
Expand Down Expand Up @@ -3763,7 +3769,7 @@ mod test_map {
let drained = map.drain_filter(|&k, _| k % 2 == 0);
let mut out = drained.collect::<Vec<_>>();
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);
}
{
Expand Down
20 changes: 13 additions & 7 deletions src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,13 +352,13 @@ impl<T, S> HashSet<T, S> {
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
Expand All @@ -367,9 +367,15 @@ impl<T, S> HashSet<T, S> {
/// use hashbrown::HashSet;
///
/// let mut set: HashSet<i32> = (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<i32> = set.drain_filter(|v| v % 2 == 0).collect();
///
/// let mut evens = drained.into_iter().collect::<Vec<_>>();
/// let mut odds = set.into_iter().collect::<Vec<_>>();
/// 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<F>(&mut self, f: F) -> DrainFilter<'_, T, F>
Expand Down Expand Up @@ -2074,7 +2080,7 @@ mod test_set {
let drained = set.drain_filter(|&k| k % 2 == 0);
let mut out = drained.collect::<Vec<_>>();
out.sort_unstable();
assert_eq!(vec![1, 3, 5, 7], out);
assert_eq!(vec![0, 2, 4, 6], out);
assert_eq!(set.len(), 4);
}
{
Expand Down

0 comments on commit 7654023

Please sign in to comment.