Skip to content

Commit f665b31

Browse files
committed
Auto merge of rust-lang#114136 - TennyZhuang:linked-list-retain, r=thomcc
add LinkedList::{retain,retain_mut} Implement rust-lang#114135 The API is consistent with other collections.
2 parents 37b2813 + 5df60f4 commit f665b31

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

library/alloc/src/collections/linked_list.rs

+93
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,99 @@ impl<T, A: Allocator> LinkedList<T, A> {
10261026
}
10271027
}
10281028

1029+
/// Retains only the elements specified by the predicate.
1030+
///
1031+
/// In other words, remove all elements `e` for which `f(&e)` returns false.
1032+
/// This method operates in place, visiting each element exactly once in the
1033+
/// original order, and preserves the order of the retained elements.
1034+
///
1035+
/// # Examples
1036+
///
1037+
/// ```
1038+
/// #![feature(linked_list_retain)]
1039+
/// use std::collections::LinkedList;
1040+
///
1041+
/// let mut d = LinkedList::new();
1042+
///
1043+
/// d.push_front(1);
1044+
/// d.push_front(2);
1045+
/// d.push_front(3);
1046+
///
1047+
/// d.retain(|&x| x % 2 == 0);
1048+
///
1049+
/// assert_eq!(d.pop_front(), Some(2));
1050+
/// assert_eq!(d.pop_front(), None);
1051+
/// ```
1052+
///
1053+
/// Because the elements are visited exactly once in the original order,
1054+
/// external state may be used to decide which elements to keep.
1055+
///
1056+
/// ```
1057+
/// #![feature(linked_list_retain)]
1058+
/// use std::collections::LinkedList;
1059+
///
1060+
/// let mut d = LinkedList::new();
1061+
///
1062+
/// d.push_front(1);
1063+
/// d.push_front(2);
1064+
/// d.push_front(3);
1065+
///
1066+
/// let keep = [false, true, false];
1067+
/// let mut iter = keep.iter();
1068+
/// d.retain(|_| *iter.next().unwrap());
1069+
/// assert_eq!(d.pop_front(), Some(2));
1070+
/// assert_eq!(d.pop_front(), None);
1071+
/// ```
1072+
#[unstable(feature = "linked_list_retain", issue = "114135")]
1073+
pub fn retain<F>(&mut self, mut f: F)
1074+
where
1075+
F: FnMut(&T) -> bool,
1076+
{
1077+
self.retain_mut(|elem| f(elem));
1078+
}
1079+
1080+
/// Retains only the elements specified by the predicate.
1081+
///
1082+
/// In other words, remove all elements `e` for which `f(&e)` returns false.
1083+
/// This method operates in place, visiting each element exactly once in the
1084+
/// original order, and preserves the order of the retained elements.
1085+
///
1086+
/// # Examples
1087+
///
1088+
/// ```
1089+
/// #![feature(linked_list_retain)]
1090+
/// use std::collections::LinkedList;
1091+
///
1092+
/// let mut d = LinkedList::new();
1093+
///
1094+
/// d.push_front(1);
1095+
/// d.push_front(2);
1096+
/// d.push_front(3);
1097+
///
1098+
/// d.retain_mut(|x| if *x % 2 == 0 {
1099+
/// *x += 1;
1100+
/// true
1101+
/// } else {
1102+
/// false
1103+
/// });
1104+
/// assert_eq!(d.pop_front(), Some(3));
1105+
/// assert_eq!(d.pop_front(), None);
1106+
/// ```
1107+
#[unstable(feature = "linked_list_retain", issue = "114135")]
1108+
pub fn retain_mut<F>(&mut self, mut f: F)
1109+
where
1110+
F: FnMut(&mut T) -> bool,
1111+
{
1112+
let mut cursor = self.cursor_front_mut();
1113+
while let Some(node) = cursor.current() {
1114+
if !f(node) {
1115+
cursor.remove_current().unwrap();
1116+
} else {
1117+
cursor.move_next();
1118+
}
1119+
}
1120+
}
1121+
10291122
/// Creates an iterator which uses a closure to determine if an element should be removed.
10301123
///
10311124
/// If the closure returns true, then the element is removed and yielded.

0 commit comments

Comments
 (0)