Skip to content

Commit e82b4ac

Browse files
PopogPopog
Popog
authored and
Popog
committed
Added Retain Iterator
.retain() now returns an iterator with the removed items closes indexmap-rs#11 Also cleaned up some match statements.
1 parent f46145b commit e82b4ac

File tree

1 file changed

+98
-23
lines changed

1 file changed

+98
-23
lines changed

src/lib.rs

+98-23
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl<Sz> ShortHashProxy<Sz>
226226
/// for ch in "a short treatise on fungi".chars() {
227227
/// *letters.entry(ch).or_insert(0) += 1;
228228
/// }
229-
///
229+
///
230230
/// assert_eq!(letters[&'s'], 2);
231231
/// assert_eq!(letters[&'t'], 3);
232232
/// assert_eq!(letters[&'u'], 1);
@@ -930,22 +930,15 @@ impl<K, V, S> OrderMap<K, V, S>
930930
/// The order the elements are visited is not specified.
931931
///
932932
/// Computes in **O(n)** time (average).
933-
pub fn retain<F>(&mut self, mut keep: F)
934-
where F: FnMut(&mut K, &mut V) -> bool,
933+
pub fn retain<F>(&mut self, keep: F) -> Retain<K, V, S, F>
934+
where F: FnMut(&mut K, &mut V) -> bool
935935
{
936936
// We can use either forward or reverse scan, but forward was
937937
// faster in a microbenchmark
938-
let mut i = 0;
939-
while i < self.len() {
940-
{
941-
let entry = &mut self.entries[i];
942-
if keep(&mut entry.key, &mut entry.value) {
943-
i += 1;
944-
continue;
945-
}
946-
}
947-
self.swap_remove_index(i);
948-
// skip increment on remove
938+
Retain {
939+
i: 0,
940+
map: self,
941+
keep: keep,
949942
}
950943
}
951944
}
@@ -975,11 +968,9 @@ impl<K, V, S> OrderMap<K, V, S> {
975968
///
976969
/// Computes in **O(1)** time (average).
977970
pub fn swap_remove_index(&mut self, index: usize) -> Option<(K, V)> {
978-
let (probe, found) = match self.entries.get(index)
979-
.map(|e| self.find_existing_entry(e))
980-
{
971+
let (probe, found) = match self.entries.get(index) {
981972
None => return None,
982-
Some(t) => t,
973+
Some(e) => self.find_existing_entry(e),
983974
};
984975
Some(self.remove_found(probe, found))
985976
}
@@ -993,11 +984,9 @@ impl<K, V, S> OrderMap<K, V, S> {
993984
// However, we should probably not let this show in the public API or docs.
994985
impl<K, V, S> OrderMap<K, V, S> {
995986
fn pop_impl(&mut self) -> Option<(K, V)> {
996-
let (probe, found) = match self.entries.last()
997-
.map(|e| self.find_existing_entry(e))
998-
{
987+
let (probe, found) = match self.entries.last() {
999988
None => return None,
1000-
Some(t) => t,
989+
Some(e) => self.find_existing_entry(e),
1001990
};
1002991
debug_assert_eq!(found, self.entries.len() - 1);
1003992
Some(self.remove_found(probe, found))
@@ -1166,6 +1155,47 @@ impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> {
11661155
}
11671156
}
11681157

1158+
pub struct Retain<'a, K: 'a, V: 'a, S: 'a, F: FnMut(&mut K, &mut V) -> bool> {
1159+
map: &'a mut OrderMap<K, V, S>,
1160+
keep: F,
1161+
i: usize,
1162+
}
1163+
1164+
impl<'a, K, V, S, F> Drop for Retain<'a, K, V, S, F>
1165+
where F: FnMut(&mut K, &mut V) -> bool
1166+
{
1167+
fn drop(&mut self) {
1168+
for _ in self {}
1169+
}
1170+
}
1171+
1172+
1173+
impl<'a, K, V, S, F> Iterator for Retain<'a, K, V, S, F>
1174+
where F: FnMut(&mut K, &mut V) -> bool
1175+
{
1176+
type Item = (K, V);
1177+
1178+
fn next(&mut self) -> Option<Self::Item> {
1179+
while self.i < self.map.len() {
1180+
let keep = {
1181+
let entry = &mut self.map.entries[self.i];
1182+
(self.keep)(&mut entry.key, &mut entry.value)
1183+
};
1184+
if keep {
1185+
self.i += 1;
1186+
} else {
1187+
// skip increment on remove
1188+
return self.map.swap_remove_index(self.i);
1189+
}
1190+
}
1191+
None
1192+
}
1193+
1194+
fn size_hint(&self) -> (usize, Option<usize>) {
1195+
(0, Some(self.map.len() - self.i))
1196+
}
1197+
}
1198+
11691199
pub struct Iter<'a, K: 'a, V: 'a> {
11701200
iter: SliceIter<'a, Bucket<K, V>>,
11711201
}
@@ -1214,7 +1244,7 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
12141244
fn size_hint(&self) -> (usize, Option<usize>) {
12151245
self.iter.size_hint()
12161246
}
1217-
1247+
12181248
fn count(self) -> usize {
12191249
self.iter.len()
12201250
}
@@ -1492,6 +1522,51 @@ mod tests {
14921522
}
14931523
}
14941524

1525+
#[test]
1526+
fn retain() {
1527+
let mut insert = vec![0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
1528+
let mut map = OrderMap::new();
1529+
1530+
for &elt in &insert {
1531+
map.insert(elt, elt);
1532+
}
1533+
1534+
assert_eq!(map.keys().count(), map.len());
1535+
assert_eq!(map.keys().count(), insert.len());
1536+
for (a, b) in insert.iter().zip(map.keys()) {
1537+
assert_eq!(a, b);
1538+
}
1539+
1540+
let mut removed_ex = Vec::new();
1541+
for i in 0.. {
1542+
while insert.get(i).iter().filter(|&v| **v >= 10).next().is_some() {
1543+
removed_ex.push(insert.swap_remove(i));
1544+
}
1545+
if i > insert.len() {
1546+
break;
1547+
}
1548+
}
1549+
println!("{:?}", removed_ex);
1550+
1551+
{
1552+
let removed: Vec<_> = map.retain(|k, _| *k < 10).collect();
1553+
assert_eq!(removed.len(), removed_ex.len());
1554+
for (&a, (b, _)) in removed_ex.iter().zip(removed) {
1555+
assert_eq!(a, b);
1556+
}
1557+
}
1558+
1559+
println!("{:?}", insert);
1560+
println!("{:?}", map);
1561+
1562+
assert_eq!(map.keys().count(), insert.len());
1563+
assert_eq!(map.keys().count(), insert.len());
1564+
1565+
for (&a, &b) in insert.iter().zip(map.keys()) {
1566+
assert_eq!(a, b);
1567+
}
1568+
}
1569+
14951570
#[test]
14961571
fn remove() {
14971572
let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];

0 commit comments

Comments
 (0)