Skip to content

Commit ffeac1f

Browse files
committed
proposal for access to BTreeMap/BTreeSet first/last, #62924
1 parent 4a8c5b2 commit ffeac1f

File tree

7 files changed

+314
-11
lines changed

7 files changed

+314
-11
lines changed

src/liballoc/benches/btree/map.rs

+25
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,28 @@ pub fn iter_1000(b: &mut Bencher) {
145145
pub fn iter_100000(b: &mut Bencher) {
146146
bench_iter(b, 100000);
147147
}
148+
149+
fn bench_first_and_last(b: &mut Bencher, size: i32) {
150+
let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
151+
b.iter(|| {
152+
for _ in 0..10 {
153+
black_box(map.first_key_value());
154+
black_box(map.last_key_value());
155+
}
156+
});
157+
}
158+
159+
#[bench]
160+
pub fn first_and_last_0(b: &mut Bencher) {
161+
bench_first_and_last(b, 0);
162+
}
163+
164+
#[bench]
165+
pub fn first_and_last_100(b: &mut Bencher) {
166+
bench_first_and_last(b, 100);
167+
}
168+
169+
#[bench]
170+
pub fn first_and_last_10k(b: &mut Bencher) {
171+
bench_first_and_last(b, 10_000);
172+
}

src/liballoc/benches/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(map_first_last)]
12
#![feature(repr_simd)]
23
#![feature(test)]
34

src/liballoc/collections/btree/map.rs

+115
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,121 @@ impl<K: Ord, V> BTreeMap<K, V> {
598598
}
599599
}
600600

601+
/// Returns the first key-value pair in the map.
602+
/// The key in this pair is the minimum key in the map.
603+
///
604+
/// # Examples
605+
///
606+
/// Basic usage:
607+
///
608+
/// ```
609+
/// #![feature(map_first_last)]
610+
/// use std::collections::BTreeMap;
611+
///
612+
/// let mut map = BTreeMap::new();
613+
/// assert_eq!(map.first_key_value(), None);
614+
/// map.insert(1, "b");
615+
/// map.insert(2, "a");
616+
/// assert_eq!(map.first_key_value(), Some((&1, &"b")));
617+
/// ```
618+
#[unstable(feature = "map_first_last", issue = "62924")]
619+
pub fn first_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
620+
where T: Ord, K: Borrow<T>
621+
{
622+
let front = first_leaf_edge(self.root.as_ref());
623+
front.right_kv().ok().map(Handle::into_kv)
624+
}
625+
626+
/// Returns the first entry in the map for in-place manipulation.
627+
/// The key of this entry is the minimum key in the map.
628+
///
629+
/// # Examples
630+
///
631+
/// Contrived way to `clear` a map:
632+
///
633+
/// ```
634+
/// #![feature(map_first_last)]
635+
/// use std::collections::BTreeMap;
636+
///
637+
/// let mut map = BTreeMap::new();
638+
/// map.insert(1, "a");
639+
/// map.insert(2, "b");
640+
/// while let Some(entry) = map.first_entry() {
641+
/// let (key, val) = entry.remove_entry();
642+
/// assert!(!map.contains_key(&key));
643+
/// }
644+
/// ```
645+
#[unstable(feature = "map_first_last", issue = "62924")]
646+
pub fn first_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
647+
where T: Ord, K: Borrow<T>
648+
{
649+
match self.length {
650+
0 => None,
651+
_ => Some(OccupiedEntry {
652+
handle: self.root.as_mut().first_kv(),
653+
length: &mut self.length,
654+
_marker: PhantomData,
655+
}),
656+
}
657+
}
658+
659+
/// Returns the last key-value pair in the map.
660+
/// The key in this pair is the maximum key in the map.
661+
///
662+
/// # Examples
663+
///
664+
/// Basic usage:
665+
///
666+
/// ```
667+
/// #![feature(map_first_last)]
668+
/// use std::collections::BTreeMap;
669+
///
670+
/// let mut map = BTreeMap::new();
671+
/// map.insert(1, "b");
672+
/// map.insert(2, "a");
673+
/// assert_eq!(map.last_key_value(), Some((&2, &"a")));
674+
/// ```
675+
#[unstable(feature = "map_first_last", issue = "62924")]
676+
pub fn last_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
677+
where T: Ord, K: Borrow<T>
678+
{
679+
let back = last_leaf_edge(self.root.as_ref());
680+
back.left_kv().ok().map(Handle::into_kv)
681+
}
682+
683+
/// Returns the last entry in the map for in-place manipulation.
684+
/// The key of this entry is the maximum key in the map.
685+
///
686+
/// # Examples
687+
///
688+
/// Contrived way to `clear` a map:
689+
///
690+
/// ```
691+
/// #![feature(map_first_last)]
692+
/// use std::collections::BTreeMap;
693+
///
694+
/// let mut map = BTreeMap::new();
695+
/// map.insert(1, "a");
696+
/// map.insert(2, "b");
697+
/// while let Some(entry) = map.last_entry() {
698+
/// let (key, val) = entry.remove_entry();
699+
/// assert!(!map.contains_key(&key));
700+
/// }
701+
/// ```
702+
#[unstable(feature = "map_first_last", issue = "62924")]
703+
pub fn last_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
704+
where T: Ord, K: Borrow<T>
705+
{
706+
match self.length {
707+
0 => None,
708+
_ => Some(OccupiedEntry {
709+
handle: self.root.as_mut().last_kv(),
710+
length: &mut self.length,
711+
_marker: PhantomData,
712+
}),
713+
}
714+
}
715+
601716
/// Returns `true` if the map contains a value for the specified key.
602717
///
603718
/// The key may be any borrowed form of the map's key type, but the ordering

src/liballoc/collections/btree/set.rs

+99-11
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,16 @@ pub struct Difference<'a, T: 'a> {
194194
#[derive(Debug)]
195195
enum DifferenceInner<'a, T: 'a> {
196196
Stitch {
197-
// iterate all of self and some of other, spotting matches along the way
197+
// iterate all of `self` and some of `other`, spotting matches along the way
198198
self_iter: Iter<'a, T>,
199199
other_iter: Peekable<Iter<'a, T>>,
200200
},
201201
Search {
202-
// iterate a small set, look up in the large set
202+
// iterate `self`, look up in `other`
203203
self_iter: Iter<'a, T>,
204204
other_set: &'a BTreeSet<T>,
205205
},
206-
Iterate(Iter<'a, T>), // simply stream self's elements
206+
Iterate(Iter<'a, T>), // simply produce all values in `self`
207207
}
208208

209209
#[stable(feature = "collection_debug", since = "1.17.0")]
@@ -356,7 +356,7 @@ impl<T: Ord> BTreeSet<T> {
356356
#[stable(feature = "rust1", since = "1.0.0")]
357357
pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
358358
let (self_min, self_max) = if let (Some(self_min), Some(self_max)) =
359-
(self.iter().next(), self.iter().next_back())
359+
(self.first(), self.last())
360360
{
361361
(self_min, self_max)
362362
} else {
@@ -365,7 +365,7 @@ impl<T: Ord> BTreeSet<T> {
365365
};
366366
};
367367
let (other_min, other_max) = if let (Some(other_min), Some(other_max)) =
368-
(other.iter().next(), other.iter().next_back())
368+
(other.first(), other.last())
369369
{
370370
(other_min, other_max)
371371
} else {
@@ -450,7 +450,7 @@ impl<T: Ord> BTreeSet<T> {
450450
#[stable(feature = "rust1", since = "1.0.0")]
451451
pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>) -> Intersection<'a, T> {
452452
let (self_min, self_max) = if let (Some(self_min), Some(self_max)) =
453-
(self.iter().next(), self.iter().next_back())
453+
(self.first(), self.last())
454454
{
455455
(self_min, self_max)
456456
} else {
@@ -459,7 +459,7 @@ impl<T: Ord> BTreeSet<T> {
459459
};
460460
};
461461
let (other_min, other_max) = if let (Some(other_min), Some(other_max)) =
462-
(other.iter().next(), other.iter().next_back())
462+
(other.first(), other.last())
463463
{
464464
(other_min, other_max)
465465
} else {
@@ -625,14 +625,14 @@ impl<T: Ord> BTreeSet<T> {
625625
return false;
626626
}
627627
let (self_min, self_max) = if let (Some(self_min), Some(self_max)) =
628-
(self.iter().next(), self.iter().next_back())
628+
(self.first(), self.last())
629629
{
630630
(self_min, self_max)
631631
} else {
632632
return true; // self is empty
633633
};
634634
let (other_min, other_max) = if let (Some(other_min), Some(other_max)) =
635-
(other.iter().next(), other.iter().next_back())
635+
(other.first(), other.last())
636636
{
637637
(other_min, other_max)
638638
} else {
@@ -654,14 +654,12 @@ impl<T: Ord> BTreeSet<T> {
654654
Less => (),
655655
}
656656
if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
657-
// Big difference in number of elements.
658657
for next in self_iter {
659658
if !other.contains(next) {
660659
return false;
661660
}
662661
}
663662
} else {
664-
// Self is not much smaller than other set.
665663
let mut other_iter = other.iter();
666664
other_iter.next();
667665
other_iter.next_back();
@@ -702,6 +700,96 @@ impl<T: Ord> BTreeSet<T> {
702700
other.is_subset(self)
703701
}
704702

703+
/// Returns a reference to the first value in the set, if any.
704+
/// This value is always the minimum of all values in the set.
705+
///
706+
/// # Examples
707+
///
708+
/// Basic usage:
709+
///
710+
/// ```
711+
/// #![feature(map_first_last)]
712+
/// use std::collections::BTreeSet;
713+
///
714+
/// let mut map = BTreeSet::new();
715+
/// assert_eq!(map.first(), None);
716+
/// map.insert(1);
717+
/// assert_eq!(map.first(), Some(&1));
718+
/// map.insert(2);
719+
/// assert_eq!(map.first(), Some(&1));
720+
/// ```
721+
#[unstable(feature = "map_first_last", issue = "62924")]
722+
pub fn first(&self) -> Option<&T> {
723+
self.map.first_key_value().map(|(k, _)| k)
724+
}
725+
726+
/// Returns a reference to the last value in the set, if any.
727+
/// This value is always the maximum of all values in the set.
728+
///
729+
/// # Examples
730+
///
731+
/// Basic usage:
732+
///
733+
/// ```
734+
/// #![feature(map_first_last)]
735+
/// use std::collections::BTreeSet;
736+
///
737+
/// let mut map = BTreeSet::new();
738+
/// assert_eq!(map.first(), None);
739+
/// map.insert(1);
740+
/// assert_eq!(map.last(), Some(&1));
741+
/// map.insert(2);
742+
/// assert_eq!(map.last(), Some(&2));
743+
/// ```
744+
#[unstable(feature = "map_first_last", issue = "62924")]
745+
pub fn last(&self) -> Option<&T> {
746+
self.map.last_key_value().map(|(k, _)| k)
747+
}
748+
749+
/// Removes the first value from the set and returns it, if any.
750+
/// The first value is always the minimum value in the set.
751+
///
752+
/// # Examples
753+
///
754+
/// ```
755+
/// #![feature(map_first_last)]
756+
/// use std::collections::BTreeSet;
757+
///
758+
/// let mut set = BTreeSet::new();
759+
///
760+
/// set.insert(1);
761+
/// while let Some(n) = set.pop_first() {
762+
/// assert_eq!(n, 1);
763+
/// }
764+
/// assert!(set.is_empty());
765+
/// ```
766+
#[unstable(feature = "map_first_last", issue = "62924")]
767+
pub fn pop_first(&mut self) -> Option<T> {
768+
self.map.first_entry().map(|entry| entry.remove_entry().0)
769+
}
770+
771+
/// Removes the last value from the set and returns it, if any.
772+
/// The last value is always the maximum value in the set.
773+
///
774+
/// # Examples
775+
///
776+
/// ```
777+
/// #![feature(map_first_last)]
778+
/// use std::collections::BTreeSet;
779+
///
780+
/// let mut set = BTreeSet::new();
781+
///
782+
/// set.insert(1);
783+
/// while let Some(n) = set.pop_last() {
784+
/// assert_eq!(n, 1);
785+
/// }
786+
/// assert!(set.is_empty());
787+
/// ```
788+
#[unstable(feature = "map_first_last", issue = "62924")]
789+
pub fn pop_last(&mut self) -> Option<T> {
790+
self.map.last_entry().map(|entry| entry.remove_entry().0)
791+
}
792+
705793
/// Adds a value to the set.
706794
///
707795
/// If the set did not have this value present, `true` is returned.

0 commit comments

Comments
 (0)