@@ -220,6 +220,28 @@ impl<T> LinkedList<T> {
220220 node
221221 } )
222222 }
223+
224+ /// Unlinks the specified node from the current list.
225+ ///
226+ /// Warning: this will not check that the provided node belongs to the current list.
227+ #[ inline]
228+ unsafe fn unlink_node ( & mut self , mut node : Shared < Node < T > > ) {
229+ let node = node. as_mut ( ) ;
230+
231+ match node. prev {
232+ Some ( mut prev) => prev. as_mut ( ) . next = node. next . clone ( ) ,
233+ // this node is the head node
234+ None => self . head = node. next . clone ( ) ,
235+ } ;
236+
237+ match node. next {
238+ Some ( mut next) => next. as_mut ( ) . prev = node. prev . clone ( ) ,
239+ // this node is the tail node
240+ None => self . tail = node. prev . clone ( ) ,
241+ } ;
242+
243+ self . len -= 1 ;
244+ }
223245}
224246
225247#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -722,6 +744,50 @@ impl<T> LinkedList<T> {
722744 second_part
723745 }
724746
747+ /// Removes any element matching the given predicate. Returns the elements which were removed
748+ /// in a new list.
749+ ///
750+ /// This operation should compute in O(n) time.
751+ ///
752+ /// # Examples
753+ ///
754+ /// ```
755+ /// #![feature(linked_list_remove_if)]
756+ ///
757+ /// use std::collections::LinkedList;
758+ ///
759+ /// let mut d = LinkedList::new();
760+ /// d.push_back(1);
761+ /// d.push_back(2);
762+ /// d.push_back(3);
763+ /// assert_eq!(d.remove_if(|v| *v < 3).len(), 2);
764+ /// assert_eq!(d.len(), 1);
765+ /// ```
766+ #[ unstable( feature = "linked_list_remove_if" ,
767+ reason = "experimental method" ,
768+ issue = "0" ) ]
769+ pub fn remove_if < P > ( & mut self , predicate : P ) -> LinkedList < T >
770+ where P : Fn ( & T ) -> bool
771+ {
772+ let mut deleted = LinkedList :: new ( ) ;
773+
774+ let mut it = self . head ;
775+
776+ while let Some ( node) = it {
777+ unsafe {
778+ it = node. as_ref ( ) . next ;
779+
780+ if predicate ( & node. as_ref ( ) . element ) {
781+ self . unlink_node ( node) ;
782+ // move the unlinked node into the deleted list.
783+ deleted. push_back_node ( Box :: from_raw ( node. as_ptr ( ) ) ) ;
784+ }
785+ }
786+ }
787+
788+ deleted
789+ }
790+
725791 /// Returns a place for insertion at the front of the list.
726792 ///
727793 /// Using this method with placement syntax is equivalent to
@@ -1502,4 +1568,17 @@ mod tests {
15021568 }
15031569 assert_eq ! ( i, v. len( ) ) ;
15041570 }
1571+
1572+ #[ test]
1573+ fn remove_if_test ( ) {
1574+ let mut m: LinkedList < u32 > = LinkedList :: new ( ) ;
1575+ m. extend ( & [ 1 , 2 , 3 , 4 , 5 , 6 ] ) ;
1576+ let deleted = m. remove_if ( |v| * v < 4 ) ;
1577+
1578+ check_links ( & m) ;
1579+ check_links ( & deleted) ;
1580+
1581+ assert_eq ! ( deleted. into_iter( ) . collect:: <Vec <_>>( ) , & [ 1 , 2 , 3 ] ) ;
1582+ assert_eq ! ( m. into_iter( ) . collect:: <Vec <_>>( ) , & [ 4 , 5 , 6 ] ) ;
1583+ }
15051584}
0 commit comments