Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BTreeMap first last proposal tweaks #70850

Merged
merged 3 commits into from
Apr 8, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 76 additions & 48 deletions src/liballoc/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,11 +653,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.first_key_value(), Some((&1, &"b")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_key_value(&self) -> Option<(&K, &V)> {
let front = self.root.as_ref()?.as_ref().first_leaf_edge();
front.right_kv().ok().map(Handle::into_kv)
}
Expand All @@ -667,36 +663,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.first_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.first_entry() {
/// if *entry.key() > 0 {
/// entry.insert("first");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "first");
/// assert_eq!(*map.get(&2).unwrap(), "b");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let front = self.root.as_mut()?.as_mut().first_leaf_edge();
if let Ok(kv) = front.right_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = front.right_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the first element in the map.
/// The key of this element is the minimum key that was in the map.
///
/// # Examples
///
/// Draining elements in ascending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_first() {
/// assert!(map.iter().all(|(k, _v)| *k > key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_first(&mut self) -> Option<(K, V)> {
self.first_entry().map(|entry| entry.remove_entry())
}

/// Returns the last key-value pair in the map.
Expand All @@ -716,11 +730,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.last_key_value(), Some((&2, &"a")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_key_value(&self) -> Option<(&K, &V)> {
let back = self.root.as_ref()?.as_ref().last_leaf_edge();
back.left_kv().ok().map(Handle::into_kv)
}
Expand All @@ -730,36 +740,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.last_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.last_entry() {
/// if *entry.key() > 0 {
/// entry.insert("last");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "a");
/// assert_eq!(*map.get(&2).unwrap(), "last");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let back = self.root.as_mut()?.as_mut().last_leaf_edge();
if let Ok(kv) = back.left_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = back.left_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the last element in the map.
/// The key of this element is the maximum key that was in the map.
///
/// # Examples
///
/// Draining elements in descending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_last() {
/// assert!(map.iter().all(|(k, _v)| *k < key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_last(&mut self) -> Option<(K, V)> {
self.last_entry().map(|entry| entry.remove_entry())
}

/// Returns `true` if the map contains a value for the specified key.
Expand Down