pub fn drain_filter<T>(vector: &mut Vec<T>, mut predicate: impl FnMut(&T) -> bool) -> Vec<T> {
let mut result = vec![];
let mut i = 0;
while i < vector.len() {
let item = &vector[i];
if predicate(item) {
let removed_item = vector.swap_remove(i);
result.push(removed_item);
continue;
}
i += 1;
}
return result;
}
#[cfg(test)]
mod tests {
use crate::drain_filter;
#[test]
fn drains_the_vector() {
let mut test_vector = vec![
true,
false,
false,
true,
true,
false,
false,
false,
];
let removed = drain_filter(&mut test_vector, |el| {
return *el;
});
assert_eq!(
removed.len(),
3,
"Must remove all elements equal to \"true\"."
);
assert!(
!removed.contains(&false),
"Removed elements vector must not contain \"false\" values."
);
assert_eq!(
test_vector.len(),
5,
"Original vector must retain \"false\" values."
);
assert!(
!test_vector.contains(&true),
"Original vector must not contain \"true\" values."
);
}
#[test]
fn works_with_non_clone_items() {
struct TestStruct {
pub flag: bool,
}
let mut test_vector = vec![
TestStruct { flag: false },
TestStruct { flag: true },
TestStruct { flag: false },
TestStruct { flag: true },
TestStruct { flag: false },
TestStruct { flag: true },
TestStruct { flag: false },
TestStruct { flag: true },
TestStruct { flag: true },
];
let removed = drain_filter(&mut test_vector, |el| {
return el.flag;
});
assert_eq!(
removed.len(),
5,
"Must remove all elements equal to \"true\"."
);
assert_eq!(
test_vector.len(),
4,
"Must retain all elements equal to \"false\"."
);
}
}