@@ -16,7 +16,8 @@ mod tests;
1616pub use self :: core:: raw_entry_v1:: { self , RawEntryApiV1 } ;
1717pub use self :: core:: { Entry , IndexedEntry , OccupiedEntry , VacantEntry } ;
1818pub use self :: iter:: {
19- Drain , IntoIter , IntoKeys , IntoValues , Iter , IterMut , IterMut2 , Keys , Splice , Values , ValuesMut ,
19+ Drain , ExtractIf , IntoIter , IntoKeys , IntoValues , Iter , IterMut , IterMut2 , Keys , Splice ,
20+ Values , ValuesMut ,
2021} ;
2122pub use self :: mutable:: MutableEntryKey ;
2223pub use self :: mutable:: MutableKeys ;
@@ -36,7 +37,7 @@ use alloc::vec::Vec;
3637#[ cfg( feature = "std" ) ]
3738use std:: collections:: hash_map:: RandomState ;
3839
39- use self :: core:: IndexMapCore ;
40+ pub ( crate ) use self :: core:: { ExtractCore , IndexMapCore } ;
4041use crate :: util:: { third, try_simplify_range} ;
4142use crate :: { Bucket , Entries , Equivalent , GetDisjointMutError , HashValue , TryReserveError } ;
4243
@@ -307,6 +308,44 @@ impl<K, V, S> IndexMap<K, V, S> {
307308 Drain :: new ( self . core . drain ( range) )
308309 }
309310
311+ /// Creates an iterator which uses a closure to determine if an element should be removed.
312+ ///
313+ /// If the closure returns true, the element is removed from the map and yielded.
314+ /// If the closure returns false, or panics, the element remains in the map and will not be
315+ /// yielded.
316+ ///
317+ /// Note that `extract_if` lets you mutate every value in the filter closure, regardless of
318+ /// whether you choose to keep or remove it.
319+ ///
320+ /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
321+ /// or the iteration short-circuits, then the remaining elements will be retained.
322+ /// Use [`retain`] with a negated predicate if you do not need the returned iterator.
323+ ///
324+ /// [`retain`]: IndexMap::retain
325+ ///
326+ /// # Examples
327+ ///
328+ /// Splitting a map into even and odd keys, reusing the original map:
329+ ///
330+ /// ```
331+ /// use indexmap::IndexMap;
332+ ///
333+ /// let mut map: IndexMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
334+ /// let extracted: IndexMap<i32, i32> = map.extract_if(|k, _v| k % 2 == 0).collect();
335+ ///
336+ /// let evens = extracted.keys().copied().collect::<Vec<_>>();
337+ /// let odds = map.keys().copied().collect::<Vec<_>>();
338+ ///
339+ /// assert_eq!(evens, vec![0, 2, 4, 6]);
340+ /// assert_eq!(odds, vec![1, 3, 5, 7]);
341+ /// ```
342+ pub fn extract_if < F > ( & mut self , pred : F ) -> ExtractIf < ' _ , K , V , F >
343+ where
344+ F : FnMut ( & K , & mut V ) -> bool ,
345+ {
346+ ExtractIf :: new ( & mut self . core , pred)
347+ }
348+
310349 /// Splits the collection into two at the given index.
311350 ///
312351 /// Returns a newly allocated map containing the elements in the range
0 commit comments