Skip to content

Commit 0c228e3

Browse files
committed
Auto merge of #187 - mbrubeck:drain_filter_reverse, r=Amanieu
Reverse `drain_filter` behavior to match libstd Fixes #186. This is the worst sort of silent breaking change, but we don't have much choice here.
2 parents 101c045 + 86abd6c commit 0c228e3

File tree

3 files changed

+31
-14
lines changed

3 files changed

+31
-14
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Changed
11+
- `drain_filter` now removes and yields items that do match the predicate,
12+
rather than items that don't. This is a **breaking change** to match the
13+
behavior of the `drain_filter` methods in `std`.
14+
1015
## [v0.8.2] - 2020-08-08
1116

1217
### Changed

src/map.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -584,24 +584,30 @@ impl<K, V, S> HashMap<K, V, S> {
584584
}
585585
}
586586

587-
/// Drains elements which are false under the given predicate,
587+
/// Drains elements which are true under the given predicate,
588588
/// and returns an iterator over the removed items.
589589
///
590-
/// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `false` out
590+
/// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `true` out
591591
/// into another iterator.
592592
///
593-
/// When the returned DrainedFilter is dropped, the elements that don't satisfy
593+
/// When the returned DrainedFilter is dropped, any remaining elements that satisfy
594594
/// the predicate are dropped from the table.
595595
///
596596
/// # Examples
597597
///
598598
/// ```
599599
/// use hashbrown::HashMap;
600600
///
601-
/// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
602-
/// let drained = map.drain_filter(|&k, _| k % 2 == 0);
603-
/// assert_eq!(drained.count(), 4);
604-
/// assert_eq!(map.len(), 4);
601+
/// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
602+
/// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect();
603+
///
604+
/// let mut evens = drained.keys().copied().collect::<Vec<_>>();
605+
/// let mut odds = map.keys().copied().collect::<Vec<_>>();
606+
/// evens.sort();
607+
/// odds.sort();
608+
///
609+
/// assert_eq!(evens, vec![0, 2, 4, 6]);
610+
/// assert_eq!(odds, vec![1, 3, 5, 7]);
605611
/// ```
606612
#[cfg_attr(feature = "inline-more", inline)]
607613
pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F>
@@ -1401,7 +1407,7 @@ impl<K, V> DrainFilterInner<'_, K, V> {
14011407
unsafe {
14021408
while let Some(item) = self.iter.next() {
14031409
let &mut (ref key, ref mut value) = item.as_mut();
1404-
if !f(key, value) {
1410+
if f(key, value) {
14051411
return Some(self.table.remove(item));
14061412
}
14071413
}

src/set.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -352,13 +352,13 @@ impl<T, S> HashSet<T, S> {
352352
self.map.retain(|k, _| f(k));
353353
}
354354

355-
/// Drains elements which are false under the given predicate,
355+
/// Drains elements which are true under the given predicate,
356356
/// and returns an iterator over the removed items.
357357
///
358-
/// In other words, move all elements `e` such that `f(&e)` returns `false` out
358+
/// In other words, move all elements `e` such that `f(&e)` returns `true` out
359359
/// into another iterator.
360360
///
361-
/// When the returned DrainedFilter is dropped, the elements that don't satisfy
361+
/// When the returned DrainedFilter is dropped, any remaining elements that satisfy
362362
/// the predicate are dropped from the set.
363363
///
364364
/// # Examples
@@ -367,9 +367,15 @@ impl<T, S> HashSet<T, S> {
367367
/// use hashbrown::HashSet;
368368
///
369369
/// let mut set: HashSet<i32> = (0..8).collect();
370-
/// let drained = set.drain_filter(|&k| k % 2 == 0);
371-
/// assert_eq!(drained.count(), 4);
372-
/// assert_eq!(set.len(), 4);
370+
/// let drained: HashSet<i32> = set.drain_filter(|v| v % 2 == 0).collect();
371+
///
372+
/// let mut evens = drained.into_iter().collect::<Vec<_>>();
373+
/// let mut odds = set.into_iter().collect::<Vec<_>>();
374+
/// evens.sort();
375+
/// odds.sort();
376+
///
377+
/// assert_eq!(evens, vec![0, 2, 4, 6]);
378+
/// assert_eq!(odds, vec![1, 3, 5, 7]);
373379
/// ```
374380
#[cfg_attr(feature = "inline-more", inline)]
375381
pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, T, F>

0 commit comments

Comments
 (0)