@@ -107,6 +107,33 @@ impl<T: State> Value<List<T>> {
107107 } ) ;
108108 }
109109
110+ /// Return all values matching the predicate.
111+ ///
112+ /// Note that unlike `Vec::extract_if`, this will allocate a vector for the result
113+ pub fn extract_if < F > ( & mut self , mut f : F ) -> Vec < Value < T > >
114+ where
115+ F : FnMut ( & Value < T > ) -> bool ,
116+ {
117+ let key = self . key ;
118+ self . with_mut ( |List { inner : list, .. } | {
119+ let mut extraction = vec ! [ ] ;
120+
121+ let mut del = 0 ;
122+
123+ for i in 0 ..list. len ( ) {
124+ let index = i - del;
125+ if f ( & list[ index] ) {
126+ let value = list. remove ( index) . expect ( "value is present" ) ;
127+ extraction. push ( value) ;
128+ changed ( key, Change :: Removed ( index as u32 ) ) ;
129+ del += 1 ;
130+ }
131+ }
132+
133+ extraction
134+ } )
135+ }
136+
110137 /// Get a reference to a value
111138 pub fn get < ' a > ( & ' a self , index : usize ) -> Option < Shared < ' a , T > > {
112139 let list = & * self . to_ref ( ) ;
@@ -361,6 +388,26 @@ mod test {
361388 assert ! ( matches!( changes. remove( 0 ) , ( _, Change :: Removed ( 1 ) ) ) ) ;
362389 }
363390
391+ #[ test]
392+ fn notify_extract_if ( ) {
393+ let mut list = Value :: new ( List :: < u32 > :: empty ( ) ) ;
394+ list. push_back ( 1 ) ;
395+ list. push_back ( 2 ) ;
396+ list. push_back ( 3 ) ;
397+ list. push_back ( 4 ) ;
398+
399+ list. reference ( ) . subscribe ( Subscriber :: ZERO ) ;
400+
401+ let result = list. extract_if ( |val| * val. to_ref ( ) % 2 == 0 ) ;
402+
403+ let mut changes = drain_changes ( ) ;
404+ assert ! ( matches!( changes. remove( 0 ) , ( _, Change :: Removed ( 2 ) ) ) ) ;
405+ assert ! ( matches!( changes. remove( 0 ) , ( _, Change :: Removed ( 1 ) ) ) ) ;
406+
407+ assert_eq ! ( * result[ 0 ] . to_ref( ) , 2 ) ;
408+ assert_eq ! ( * result[ 1 ] . to_ref( ) , 4 ) ;
409+ }
410+
364411 #[ test]
365412 fn notify_pop_back ( ) {
366413 let mut list = Value :: new ( List :: < u32 > :: empty ( ) ) ;
0 commit comments