@@ -220,6 +220,28 @@ impl<T> LinkedList<T> {
220
220
node
221
221
} )
222
222
}
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
+ }
223
245
}
224
246
225
247
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -722,6 +744,50 @@ impl<T> LinkedList<T> {
722
744
second_part
723
745
}
724
746
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
+
725
791
/// Returns a place for insertion at the front of the list.
726
792
///
727
793
/// Using this method with placement syntax is equivalent to
@@ -1502,4 +1568,17 @@ mod tests {
1502
1568
}
1503
1569
assert_eq ! ( i, v. len( ) ) ;
1504
1570
}
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
+ }
1505
1584
}
0 commit comments