Skip to content

Commit

Permalink
Rollup merge of rust-lang#114136 - TennyZhuang:linked-list-retain, r=…
Browse files Browse the repository at this point in the history
…thomcc

add LinkedList::{retain,retain_mut}

Implement rust-lang#114135

The API is consistent with other collections.
  • Loading branch information
GuillaumeGomez committed Dec 8, 2023
2 parents 5ea6256 + 5df60f4 commit 27ea9ab
Showing 1 changed file with 93 additions and 0 deletions.
93 changes: 93 additions & 0 deletions library/alloc/src/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,99 @@ impl<T, A: Allocator> LinkedList<T, A> {
}
}

/// Retains only the elements specified by the predicate.
///
/// In other words, remove all elements `e` for which `f(&e)` returns false.
/// This method operates in place, visiting each element exactly once in the
/// original order, and preserves the order of the retained elements.
///
/// # Examples
///
/// ```
/// #![feature(linked_list_retain)]
/// use std::collections::LinkedList;
///
/// let mut d = LinkedList::new();
///
/// d.push_front(1);
/// d.push_front(2);
/// d.push_front(3);
///
/// d.retain(|&x| x % 2 == 0);
///
/// assert_eq!(d.pop_front(), Some(2));
/// assert_eq!(d.pop_front(), None);
/// ```
///
/// Because the elements are visited exactly once in the original order,
/// external state may be used to decide which elements to keep.
///
/// ```
/// #![feature(linked_list_retain)]
/// use std::collections::LinkedList;
///
/// let mut d = LinkedList::new();
///
/// d.push_front(1);
/// d.push_front(2);
/// d.push_front(3);
///
/// let keep = [false, true, false];
/// let mut iter = keep.iter();
/// d.retain(|_| *iter.next().unwrap());
/// assert_eq!(d.pop_front(), Some(2));
/// assert_eq!(d.pop_front(), None);
/// ```
#[unstable(feature = "linked_list_retain", issue = "114135")]
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.retain_mut(|elem| f(elem));
}

/// Retains only the elements specified by the predicate.
///
/// In other words, remove all elements `e` for which `f(&e)` returns false.
/// This method operates in place, visiting each element exactly once in the
/// original order, and preserves the order of the retained elements.
///
/// # Examples
///
/// ```
/// #![feature(linked_list_retain)]
/// use std::collections::LinkedList;
///
/// let mut d = LinkedList::new();
///
/// d.push_front(1);
/// d.push_front(2);
/// d.push_front(3);
///
/// d.retain_mut(|x| if *x % 2 == 0 {
/// *x += 1;
/// true
/// } else {
/// false
/// });
/// assert_eq!(d.pop_front(), Some(3));
/// assert_eq!(d.pop_front(), None);
/// ```
#[unstable(feature = "linked_list_retain", issue = "114135")]
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let mut cursor = self.cursor_front_mut();
while let Some(node) = cursor.current() {
if !f(node) {
cursor.remove_current().unwrap();
} else {
cursor.move_next();
}
}
}

/// Creates an iterator which uses a closure to determine if an element should be removed.
///
/// If the closure returns true, then the element is removed and yielded.
Expand Down

0 comments on commit 27ea9ab

Please sign in to comment.