Introduce LinkedList::remove_if
This commit is contained in:
@@ -220,6 +220,28 @@ impl<T> LinkedList<T> {
|
|||||||
node
|
node
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unlinks the specified node from the current list.
|
||||||
|
///
|
||||||
|
/// Warning: this will not check that the provided node belongs to the current list.
|
||||||
|
#[inline]
|
||||||
|
unsafe fn unlink_node(&mut self, mut node: Shared<Node<T>>) {
|
||||||
|
let node = node.as_mut();
|
||||||
|
|
||||||
|
match node.prev {
|
||||||
|
Some(mut prev) => prev.as_mut().next = node.next.clone(),
|
||||||
|
// this node is the head node
|
||||||
|
None => self.head = node.next.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match node.next {
|
||||||
|
Some(mut next) => next.as_mut().prev = node.prev.clone(),
|
||||||
|
// this node is the tail node
|
||||||
|
None => self.tail = node.prev.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.len -= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@@ -722,6 +744,50 @@ impl<T> LinkedList<T> {
|
|||||||
second_part
|
second_part
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes any element matching the given predicate. Returns the elements which were removed
|
||||||
|
/// in a new list.
|
||||||
|
///
|
||||||
|
/// This operation should compute in O(n) time.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(linked_list_remove_if)]
|
||||||
|
///
|
||||||
|
/// use std::collections::LinkedList;
|
||||||
|
///
|
||||||
|
/// let mut d = LinkedList::new();
|
||||||
|
/// d.push_back(1);
|
||||||
|
/// d.push_back(2);
|
||||||
|
/// d.push_back(3);
|
||||||
|
/// assert_eq!(d.remove_if(|v| *v < 3).len(), 2);
|
||||||
|
/// assert_eq!(d.len(), 1);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "linked_list_remove_if",
|
||||||
|
reason = "experimental method",
|
||||||
|
issue = "0")]
|
||||||
|
pub fn remove_if<P>(&mut self, predicate: P) -> LinkedList<T>
|
||||||
|
where P: Fn(&T) -> bool
|
||||||
|
{
|
||||||
|
let mut deleted = LinkedList::new();
|
||||||
|
|
||||||
|
let mut it = self.head;
|
||||||
|
|
||||||
|
while let Some(node) = it {
|
||||||
|
unsafe {
|
||||||
|
it = node.as_ref().next;
|
||||||
|
|
||||||
|
if predicate(&node.as_ref().element) {
|
||||||
|
self.unlink_node(node);
|
||||||
|
// move the unlinked node into the deleted list.
|
||||||
|
deleted.push_back_node(Box::from_raw(node.as_ptr()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleted
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a place for insertion at the front of the list.
|
/// Returns a place for insertion at the front of the list.
|
||||||
///
|
///
|
||||||
/// Using this method with placement syntax is equivalent to
|
/// Using this method with placement syntax is equivalent to
|
||||||
@@ -1502,4 +1568,17 @@ mod tests {
|
|||||||
}
|
}
|
||||||
assert_eq!(i, v.len());
|
assert_eq!(i, v.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_if_test() {
|
||||||
|
let mut m: LinkedList<u32> = LinkedList::new();
|
||||||
|
m.extend(&[1, 2, 3, 4, 5, 6]);
|
||||||
|
let deleted = m.remove_if(|v| *v < 4);
|
||||||
|
|
||||||
|
check_links(&m);
|
||||||
|
check_links(&deleted);
|
||||||
|
|
||||||
|
assert_eq!(deleted.into_iter().collect::<Vec<_>>(), &[1, 2, 3]);
|
||||||
|
assert_eq!(m.into_iter().collect::<Vec<_>>(), &[4, 5, 6]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user