Skip to content

Commit 86c319b

Browse files
authored
Merge pull request #421 from cuviper/pop_if
Add map and set `pop_if`, similar to Rust 1.86's `Vec::pop_if`
2 parents 03f9e58 + 09fb43f commit 86c319b

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

src/map.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,36 @@ impl<K, V, S> IndexMap<K, V, S> {
11361136
self.core.pop()
11371137
}
11381138

1139+
/// Removes and returns the last key-value pair from a map if the predicate
1140+
/// returns `true`, or [`None`] if the predicate returns false or the map
1141+
/// is empty (the predicate will not be called in that case).
1142+
///
1143+
/// This preserves the order of the remaining elements.
1144+
///
1145+
/// Computes in **O(1)** time (average).
1146+
///
1147+
/// # Examples
1148+
///
1149+
/// ```
1150+
/// use indexmap::IndexMap;
1151+
///
1152+
/// let init = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')];
1153+
/// let mut map = IndexMap::from(init);
1154+
/// let pred = |key: &i32, _value: &mut char| *key % 2 == 0;
1155+
///
1156+
/// assert_eq!(map.pop_if(pred), Some((4, 'd')));
1157+
/// assert_eq!(map.as_slice(), &init[..3]);
1158+
/// assert_eq!(map.pop_if(pred), None);
1159+
/// ```
1160+
pub fn pop_if(&mut self, predicate: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)> {
1161+
let (last_key, last_value) = self.last_mut()?;
1162+
if predicate(last_key, last_value) {
1163+
self.core.pop()
1164+
} else {
1165+
None
1166+
}
1167+
}
1168+
11391169
/// Scan through each key-value pair in the map and keep those where the
11401170
/// closure `keep` returns `true`.
11411171
///

src/set.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,35 @@ impl<T, S> IndexSet<T, S> {
904904
self.map.pop().map(|(x, ())| x)
905905
}
906906

907+
/// Removes and returns the last value from a set if the predicate
908+
/// returns `true`, or [`None`] if the predicate returns false or the set
909+
/// is empty (the predicate will not be called in that case).
910+
///
911+
/// This preserves the order of the remaining elements.
912+
///
913+
/// Computes in **O(1)** time (average).
914+
///
915+
/// # Examples
916+
///
917+
/// ```
918+
/// use indexmap::IndexSet;
919+
///
920+
/// let mut set = IndexSet::from([1, 2, 3, 4]);
921+
/// let pred = |x: &i32| *x % 2 == 0;
922+
///
923+
/// assert_eq!(set.pop_if(pred), Some(4));
924+
/// assert_eq!(set.as_slice(), &[1, 2, 3]);
925+
/// assert_eq!(set.pop_if(pred), None);
926+
/// ```
927+
pub fn pop_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
928+
let last = self.last()?;
929+
if predicate(last) {
930+
self.pop()
931+
} else {
932+
None
933+
}
934+
}
935+
907936
/// Scan through each value in the set and keep those where the
908937
/// closure `keep` returns `true`.
909938
///

0 commit comments

Comments
 (0)