Skip to content

Commit 5698b84

Browse files
authored
Merge pull request #16 from cuviper/pop-if
Add map and set `pop_front_if` and `pop_back_if`
2 parents cf5604c + d9b2993 commit 5698b84

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ jobs:
113113
- uses: taiki-e/install-action@v2
114114
with:
115115
tool: cargo-nextest
116+
if: github.event_name == 'merge_group'
116117
- run: cargo miri nextest run
118+
if: github.event_name == 'merge_group'
117119
- run: cargo miri test --doc
118120

119121
minimal-versions:

src/map.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,66 @@ impl<K, V, S> RingMap<K, V, S> {
12131213
self.core.pop_front()
12141214
}
12151215

1216+
/// Removes and returns the last key-value pair from a map if the predicate
1217+
/// returns `true`, or [`None`] if the predicate returns false or the map
1218+
/// is empty (the predicate will not be called in that case).
1219+
///
1220+
/// This preserves the order of the remaining elements.
1221+
///
1222+
/// Computes in **O(1)** time (average).
1223+
///
1224+
/// # Examples
1225+
///
1226+
/// ```
1227+
/// use ringmap::RingMap;
1228+
///
1229+
/// let init = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')];
1230+
/// let mut map = RingMap::from(init);
1231+
/// let pred = |key: &i32, _value: &mut char| *key % 2 == 0;
1232+
///
1233+
/// assert_eq!(map.pop_back_if(pred), Some((4, 'd')));
1234+
/// assert_eq!(map.as_slices().0, &init[..3]);
1235+
/// assert_eq!(map.pop_back_if(pred), None);
1236+
/// ```
1237+
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)> {
1238+
let (last_key, last_value) = self.back_mut()?;
1239+
if predicate(last_key, last_value) {
1240+
self.core.pop_back()
1241+
} else {
1242+
None
1243+
}
1244+
}
1245+
1246+
/// Removes and returns the first key-value pair from a map if the predicate
1247+
/// returns `true`, or [`None`] if the predicate returns false or the map
1248+
/// is empty (the predicate will not be called in that case).
1249+
///
1250+
/// This preserves the order of the remaining elements.
1251+
///
1252+
/// Computes in **O(1)** time (average).
1253+
///
1254+
/// # Examples
1255+
///
1256+
/// ```
1257+
/// use ringmap::RingMap;
1258+
///
1259+
/// let init = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')];
1260+
/// let mut map = RingMap::from(init);
1261+
/// let pred = |key: &i32, _value: &mut char| *key % 2 == 1;
1262+
///
1263+
/// assert_eq!(map.pop_front_if(pred), Some((1, 'a')));
1264+
/// assert_eq!(map.as_slices().0, &init[1..]);
1265+
/// assert_eq!(map.pop_front_if(pred), None);
1266+
/// ```
1267+
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)> {
1268+
let (first_key, first_value) = self.front_mut()?;
1269+
if predicate(first_key, first_value) {
1270+
self.core.pop_front()
1271+
} else {
1272+
None
1273+
}
1274+
}
1275+
12161276
/// Scan through each key-value pair in the map and keep those where the
12171277
/// closure `keep` returns `true`.
12181278
///

src/set.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,64 @@ impl<T, S> RingSet<T, S> {
962962
self.map.pop_front().map(|(x, ())| x)
963963
}
964964

965+
/// Removes and returns the last value from a set if the predicate
966+
/// returns `true`, or [`None`] if the predicate returns false or the set
967+
/// is empty (the predicate will not be called in that case).
968+
///
969+
/// This preserves the order of the remaining elements.
970+
///
971+
/// Computes in **O(1)** time (average).
972+
///
973+
/// # Examples
974+
///
975+
/// ```
976+
/// use ringmap::RingSet;
977+
///
978+
/// let mut set = RingSet::from([1, 2, 3, 4]);
979+
/// let pred = |x: &i32| *x % 2 == 0;
980+
///
981+
/// assert_eq!(set.pop_back_if(pred), Some(4));
982+
/// assert_eq!(set.as_slices().0, &[1, 2, 3]);
983+
/// assert_eq!(set.pop_back_if(pred), None);
984+
/// ```
985+
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
986+
let last = self.back()?;
987+
if predicate(last) {
988+
self.pop_back()
989+
} else {
990+
None
991+
}
992+
}
993+
994+
/// Removes and returns the first value from a set if the predicate
995+
/// returns `true`, or [`None`] if the predicate returns false or the set
996+
/// is empty (the predicate will not be called in that case).
997+
///
998+
/// This preserves the order of the remaining elements.
999+
///
1000+
/// Computes in **O(1)** time (average).
1001+
///
1002+
/// # Examples
1003+
///
1004+
/// ```
1005+
/// use ringmap::RingSet;
1006+
///
1007+
/// let mut set = RingSet::from([1, 2, 3, 4]);
1008+
/// let pred = |x: &i32| *x % 2 == 1;
1009+
///
1010+
/// assert_eq!(set.pop_front_if(pred), Some(1));
1011+
/// assert_eq!(set.as_slices().0, &[2, 3, 4]);
1012+
/// assert_eq!(set.pop_front_if(pred), None);
1013+
/// ```
1014+
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
1015+
let first = self.front()?;
1016+
if predicate(first) {
1017+
self.pop_front()
1018+
} else {
1019+
None
1020+
}
1021+
}
1022+
9651023
/// Scan through each value in the set and keep those where the
9661024
/// closure `keep` returns `true`.
9671025
///

0 commit comments

Comments
 (0)