Rollup merge of #135890 - GrigorenkoPV:deque-pop-if, r=thomcc

Implement `VecDeque::pop_front_if` & `VecDeque::pop_back_if`

Tracking issue: #135889
This commit is contained in:
Matthias Krüger 2025-01-24 08:08:09 +01:00 committed by GitHub
commit be15391703
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 86 additions and 0 deletions

View file

@ -1735,6 +1735,52 @@ impl<T, A: Allocator> VecDeque<T, A> {
}
}
/// Removes and returns the first element from the deque if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the deque
/// is empty (the predicate will not be called in that case).
///
/// # Examples
///
/// ```
/// #![feature(vec_deque_pop_if)]
/// use std::collections::VecDeque;
///
/// let mut deque: VecDeque<i32> = vec![0, 1, 2, 3, 4].into();
/// let pred = |x: &mut i32| *x % 2 == 0;
///
/// assert_eq!(deque.pop_front_if(pred), Some(0));
/// assert_eq!(deque, [1, 2, 3, 4]);
/// assert_eq!(deque.pop_front_if(pred), None);
/// ```
#[unstable(feature = "vec_deque_pop_if", issue = "135889")]
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
let first = self.front_mut()?;
if predicate(first) { self.pop_front() } else { None }
}
/// Removes and returns the last element from the deque if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the deque
/// is empty (the predicate will not be called in that case).
///
/// # Examples
///
/// ```
/// #![feature(vec_deque_pop_if)]
/// use std::collections::VecDeque;
///
/// let mut deque: VecDeque<i32> = vec![0, 1, 2, 3, 4].into();
/// let pred = |x: &mut i32| *x % 2 == 0;
///
/// assert_eq!(deque.pop_back_if(pred), Some(4));
/// assert_eq!(deque, [0, 1, 2, 3]);
/// assert_eq!(deque.pop_back_if(pred), None);
/// ```
#[unstable(feature = "vec_deque_pop_if", issue = "135889")]
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
let first = self.back_mut()?;
if predicate(first) { self.pop_back() } else { None }
}
/// Prepends an element to the deque.
///
/// # Examples

View file

@ -38,6 +38,7 @@
#![feature(str_as_str)]
#![feature(strict_provenance_lints)]
#![feature(vec_pop_if)]
#![feature(vec_deque_pop_if)]
#![feature(unique_rc_arc)]
#![feature(macro_metavar_expr_concat)]
#![allow(internal_features)]

View file

@ -80,6 +80,45 @@ fn test_parameterized<T: Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) {
assert_eq!(deq[3].clone(), d.clone());
}
#[test]
fn test_pop_if() {
let mut deq: VecDeque<_> = vec![0, 1, 2, 3, 4].into();
let pred = |x: &mut i32| *x % 2 == 0;
assert_eq!(deq.pop_front_if(pred), Some(0));
assert_eq!(deq, [1, 2, 3, 4]);
assert_eq!(deq.pop_front_if(pred), None);
assert_eq!(deq, [1, 2, 3, 4]);
assert_eq!(deq.pop_back_if(pred), Some(4));
assert_eq!(deq, [1, 2, 3]);
assert_eq!(deq.pop_back_if(pred), None);
assert_eq!(deq, [1, 2, 3]);
}
#[test]
fn test_pop_if_empty() {
let mut deq = VecDeque::<i32>::new();
assert_eq!(deq.pop_front_if(|_| true), None);
assert_eq!(deq.pop_back_if(|_| true), None);
assert!(deq.is_empty());
}
#[test]
fn test_pop_if_mutates() {
let mut v: VecDeque<_> = vec![-1, 1].into();
let pred = |x: &mut i32| {
*x *= 2;
false
};
assert_eq!(v.pop_front_if(pred), None);
assert_eq!(v, [-2, 1]);
assert_eq!(v.pop_back_if(pred), None);
assert_eq!(v, [-2, 2]);
}
#[test]
fn test_push_front_grow() {
let mut deq = VecDeque::new();