15

If you have a sorted map of key/value pairs (or just keys), one of the obvious operations is to get the first or last pair (or key).

C++'s std::vector has front() and back() for this purpose. std::map doesn't, but *map.begin() and *map.rbegin() (reverse iterator) work for this (assuming one knows the map is not empty).

In Rust, getting the first element of a map seems to require map.iter().next().unwrap() — ugly, but perhaps justified considering some error checking is needed.

How can we get the last element? By stepping over all elements: map.iter().last().unwrap()?

I see that there is Iterator::rev(), so is map.iter().rev().next().unwrap() a reasonable alternative?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
dhardy
  • 11,175
  • 7
  • 38
  • 46
  • 1
    Why the unwrap? Can you structure the code so that you use the presence (or non-) of the back value in a conditional? – bluss Nov 14 '15 at 14:40
  • Good point; I ended up using `.unwrap_or(0)` for this use-case. For another I needed to know first that there was exactly one element, hence `map.iter().next().unwrap()` — a bit unwieldy way of getting the only element! – dhardy Nov 14 '15 at 22:13
  • The `first()` and `last()` methods are coming soon: https://github.com/rust-lang/rust/issues/62924 – Code4R7 Oct 10 '22 at 10:11
  • https://doc.rust-lang.org/alloc/collections/btree_map/struct.BTreeMap.html#method.last_entry – cloudsurfin Feb 27 '23 at 17:38

3 Answers3

22

btree_map::Iter, which is returned by BTreeMap::iter(), implements DoubleEndedIterator, so indeed, either the approach with rev() would work or you can use the next_back() method directly:

let (key, value) = map.iter().next_back().unwrap();
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
2

https://github.com/rust-lang/rust/issues/31690#issuecomment-184445033

A dedicated method would improve discoverability, but you can do:

let map: BTreeMap<K, V> = ...;
let min = map.iter().next();
let max = map.iter().next_back();

and the same for BTreeSet.

rubyu2
  • 270
  • 1
  • 3
  • 14
1

The Iterator::rev method requires that Self implements DoubleEndedIterator, so it should always be an optimized and correct choice for your use case.

fn rev(self) -> Rev<Self>
where
    Self: DoubleEndedIterator,
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Stargateur
  • 24,473
  • 8
  • 65
  • 91