Skip to content

Commit ea6057f

Browse files
committed
Add a TreeMap.remove_with method.
TreeMap has methods `find`, `find_mut` and `remove`, which take `&K` and return `Option` of `&V`, `&mut V` and `V`; and `find_with` and `find_with_mut` which take `|&K| -> Ordering`, but `remove_with` was missing from this symmetry.
1 parent 45cbdec commit ea6057f

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

src/libcollections/tree/map.rs

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ impl<K: Ord, V> TreeMap<K, V> {
557557
/// ```
558558
#[unstable = "matches collection reform specification, waiting for dust to settle"]
559559
pub fn remove(&mut self, key: &K) -> Option<V> {
560-
let ret = remove(&mut self.root, key);
560+
let ret = remove(&mut self.root, |x| key.cmp(x));
561561
if ret.is_some() { self.length -= 1 }
562562
ret
563563
}
@@ -618,6 +618,33 @@ impl<K, V> TreeMap<K, V> {
618618
}
619619
}
620620

621+
impl<K: Ord, V> TreeMap<K, V> {
622+
/// Returns the value for which `f(key)` returns `Equal`. `f` is invoked
623+
/// with current key and guides tree navigation. That means `f` should
624+
/// be aware of natural ordering of the tree.
625+
///
626+
/// # Example
627+
///
628+
/// ```
629+
/// use std::collections::TreeMap;
630+
///
631+
/// let mut t = TreeMap::new();
632+
/// t.insert("Content-Type".to_string(), "application/xml".to_string());
633+
/// t.insert("User-Agent".to_string(), "Curl-Rust/0.1".to_string());
634+
///
635+
/// match t.remove_with(|k| "User-Agent".cmp(k.as_slice())) {
636+
/// Some(x) => assert_eq!(x.as_slice(), "Curl-Rust/0.1"),
637+
/// None => panic!(),
638+
/// }
639+
///
640+
/// assert_eq!(t.find_with(|x| "User-Agent".cmp(x.as_slice())), None);
641+
/// ```
642+
#[inline]
643+
pub fn remove_with(&mut self, f:|&K| -> Ordering) -> Option<V> {
644+
remove(&mut self.root, f)
645+
}
646+
}
647+
621648
// range iterators.
622649

623650
macro_rules! bound_setup {
@@ -1169,7 +1196,7 @@ fn insert<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
11691196
}
11701197

11711198
fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
1172-
key: &K) -> Option<V> {
1199+
f: |&K| -> Ordering) -> Option<V> {
11731200
fn heir_swap<K: Ord, V>(node: &mut Box<TreeNode<K, V>>,
11741201
child: &mut Option<Box<TreeNode<K, V>>>) {
11751202
// *could* be done without recursion, but it won't borrow check
@@ -1188,9 +1215,9 @@ fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
11881215
return None; // bottom of tree
11891216
}
11901217
Some(ref mut save) => {
1191-
let (ret, rebalance) = match key.cmp(&save.key) {
1192-
Less => (remove(&mut save.left, key), true),
1193-
Greater => (remove(&mut save.right, key), true),
1218+
let (ret, rebalance) = match f(&save.key) {
1219+
Less => (remove(&mut save.left, f), true),
1220+
Greater => (remove(&mut save.right, f), true),
11941221
Equal => {
11951222
if save.left.is_some() {
11961223
if save.right.is_some() {
@@ -1202,7 +1229,7 @@ fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
12021229
swap(&mut save.value, &mut left.value);
12031230
}
12041231
save.left = Some(left);
1205-
(remove(&mut save.left, key), true)
1232+
(remove(&mut save.left, f), true)
12061233
} else {
12071234
let new = save.left.take().unwrap();
12081235
let box TreeNode{value, ..} = replace(save, new);
@@ -1810,6 +1837,15 @@ mod test_treemap {
18101837
assert_eq!(m.remove(&1), Some(2));
18111838
assert_eq!(m.remove(&1), None);
18121839
}
1840+
1841+
#[test]
1842+
fn test_remove_with() {
1843+
let mut m = TreeMap::new();
1844+
m.insert(1u, 2i);
1845+
assert_eq!(m.remove_with(|k| k.cmp(&1)), Some(2));
1846+
assert_eq!(m.remove(&1), None);
1847+
assert_eq!(m.remove_with(|k| k.cmp(&1)), None);
1848+
}
18131849
}
18141850

18151851
#[cfg(test)]

0 commit comments

Comments
 (0)