Skip to content

Commit

Permalink
add retain()
Browse files Browse the repository at this point in the history
  • Loading branch information
rinde committed Dec 15, 2023
1 parent a628201 commit 9502b14
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 3 deletions.
3 changes: 1 addition & 2 deletions doc/vec_map.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ Below is an overview of the all methods and traits that are implemented for `Vec
| `shift_remove_entry()` | not planned (not applicable) |
| `shift_remove_full()` | not planned (not applicable) |
| `pop()` ||
| `retain()` | planned |
| `retain_mut()` | planned |
| `retain()` ||
| `sort_keys()` | not planned (not applicable) |
| `sort_by()` | not planned (not applicable) |
| `sorted_by()` | not planned (not applicable) |
Expand Down
69 changes: 68 additions & 1 deletion src/vec_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ impl<K: IndexKey, V> VecMap<K, V> {

/// Removes the last key-value pair.
///
/// Worst case performance is O(n) in case the value is at the first index.
/// Worst case performance is O(n) in case the value is at the first index,
/// where n = the capacity.
pub fn pop(&mut self) -> Option<(K, V)> {
if self.is_empty() {
None
Expand All @@ -137,6 +138,29 @@ impl<K: IndexKey, V> VecMap<K, V> {
}
}

/// Iterates over each key-value pair in the map and keep those where the
/// closure `keep` returns `true`.
///
/// The elements are visited in order.
pub fn retain<F>(&mut self, mut keep: F)
where
F: FnMut(K, &mut V) -> bool,
{
if !self.is_empty() {
self.data
.iter_mut()
.enumerate()
.for_each(|(i, value_option)| {
if let Some(value) = value_option.as_mut() {
if !keep(K::from_index(i), value) {
self.len -= 1;
value_option.take();
}
}
});
}
}

/// Get the given key's entry in the map for insertion and/or in-place
/// manipulation.
pub fn entry(&mut self, key: K) -> Entry<K, V> {
Expand Down Expand Up @@ -386,6 +410,7 @@ macro_rules! vecmap {
let _cap = $crate::vecmap!(@count $($key),*);
let mut _map = $crate::vec_map::VecMap::with_capacity(_cap);
$(
#[allow(let_underscore_drop)]
let _ = _map.insert($key, $value);
)*
_map
Expand Down Expand Up @@ -488,6 +513,48 @@ mod test {
assert_eq!(0, map.len());
}

#[test]
fn test_retain_by_key() {
let mut map = vecmap! { 9usize => "nine".to_string(), 17 => "seventeen".to_string(), 2 => "two".to_string()};
map.retain(|k, _| k < 9);
assert_eq!(1, map.len());
assert_eq!(
vec![(2, "two".to_string())],
map.into_iter().collect::<Vec<_>>()
);
}

#[test]
fn test_retain_by_value() {
let mut map = vecmap! { 9usize => "nine".to_string(), 17 => "seventeen".to_string(), 2 => "two".to_string()};
map.retain(|_, s| s.len() > 8);
assert_eq!(1, map.len());
assert_eq!(
vec![(17, "seventeen".to_string())],
map.into_iter().collect::<Vec<_>>()
);
}

#[test]
fn test_retain_mut_value() {
let mut map = vecmap! { 9usize => "nine".to_string(), 17 => "seventeen".to_string(), 2 => "two".to_string()};
map.retain(|_, s| {
if s.len() < 8 {
s.push_str("-yes");
}
true
});
assert_eq!(3, map.len());
assert_eq!(
vec![
(2, "two-yes".to_string()),
(9, "nine-yes".to_string()),
(17, "seventeen".to_string())
],
map.into_iter().collect::<Vec<_>>()
);
}

#[test]
fn test_entry_or_insert() {
let mut map = VecMap::new();
Expand Down

0 comments on commit 9502b14

Please sign in to comment.