Change:
Associative maps ( and ) in Rust are currently missing two methods to get owning iterators to their keys or values. We have to get key-value reference pairs, to get key-value mutable reference pairs and to get owned key-value pairs. I'd expect and to offer a similar trio of methods (with an exception for of course). is there, but the variants are missing for seemingly no good reason. As an example implementation (but perhaps we can do better):
I would accept a PR to introduce unstable intokeys() and intovalues().
Hi, I’m interested in working on this but I have a question regarding the implementation. I guess we can implement this in two ways. First one is implementing like the example in the first comment, like returning . And the second option is to return a struct of its own (like a mixture of and / structs) instead of returning . We can name them IntoKeys and IntoValues and they can be responsible of implementing the trait. I feel like performance wise they are same, since map and custom struct both will be evaluated lazily when we iterate over. But there might be a rule to always return a proper type in the rust std code that I don't know. So I think I’m okay implementing either way but wanted to ask just in case. What do you think?
For the public API I would prefer this implemented using dedicated IntoKeys and IntoValues iterator types. They can be implemented internally as wrappers around Map<IntoIter<K, Vif that simplifies things.
Thanks for the answer Created a PR for this and you as a reviewer. Would you mind taking a look at it when you have time?

Discussion:
<ins> // ignore-tidy-filelength </ins> use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::Debug;

inner: IterMut<'a, K, V>, } <ins> /// An owning iterator over the keys of a `BTreeMap`. /// /// This `struct` is created by the [`into_keys`] method on [`BTreeMap`]. /// See its documentation for more. /// /// [`into_keys`]: BTreeMap::into_keys #[unstable(feature = "map_into_keys_values", issue = "75294")] #[derive(Debug)] pub struct IntoKeys<K, V> { inner: IntoIter<K, V>, } /// An owning iterator over the values of a `BTreeMap`. /// /// This `struct` is created by the [`into_values`] method on [`BTreeMap`]. /// See its documentation for more. /// /// [`into_values`]: BTreeMap::into_values #[unstable(feature = "map_into_keys_values", issue = "75294")] #[derive(Debug)] pub struct IntoValues<K, V> { inner: IntoIter<K, V>, } </ins> /// An iterator over a sub-range of entries in a `BTreeMap`. /// /// This `struct` is created by the [`range`] method on [`BTreeMap`]. See its

self.length = dfs(self.root.as_ref().unwrap().as_ref()); } <ins> /// Creates a consuming iterator visiting all the keys, in sorted order. /// The map cannot be used after calling this. /// The iterator element type is `K`. /// /// # Examples /// /// ``` /// #![feature(map_into_keys_values)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(2, "b"); /// a.insert(1, "a"); /// /// let keys: Vec<i32> = a.into_keys().collect(); /// assert_eq!(keys, [1, 2]); /// ``` #[inline] #[unstable(feature = "map_into_keys_values", issue = "75294")] pub fn into_keys(self) -> IntoKeys<K, V> { IntoKeys { inner: self.into_iter() } } /// Creates a consuming iterator visiting all the values, in order by key. /// The map cannot be used after calling this. /// The iterator element type is `V`. /// /// # Examples /// /// ``` /// #![feature(map_into_keys_values)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(1, "hello"); /// a.insert(2, "goodbye"); /// /// let values: Vec<&str> = a.into_values().collect(); /// assert_eq!(values, ["hello", "goodbye"]); /// ``` #[inline] #[unstable(feature = "map_into_keys_values", issue = "75294")] pub fn into_values(self) -> IntoValues<K, V> { IntoValues { inner: self.into_iter() } } </ins> } #[stable(feature = "rust1", since = "1.0.0")]

} } <ins> #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> Iterator for IntoKeys<K, V> { type Item = K; fn next(&mut self) -> Option<K> { self.inner.next().map(|(k, _)| k) } fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } fn last(mut self) -> Option<K> { self.next_back() } fn min(mut self) -> Option<K> { self.next() } fn max(mut self) -> Option<K> { self.next_back() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> DoubleEndedIterator for IntoKeys<K, V> { fn next_back(&mut self) -> Option<K> { self.inner.next_back().map(|(k, _)| k) } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> ExactSizeIterator for IntoKeys<K, V> { fn len(&self) -> usize { self.inner.len() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> FusedIterator for IntoKeys<K, V> {} #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> Iterator for IntoValues<K, V> { type Item = V; fn next(&mut self) -> Option<V> { self.inner.next().map(|(_, v)| v) } fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } fn last(mut self) -> Option<V> { self.next_back() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> DoubleEndedIterator for IntoValues<K, V> { fn next_back(&mut self) -> Option<V> { self.inner.next_back().map(|(_, v)| v) } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> ExactSizeIterator for IntoValues<K, V> { fn len(&self) -> usize { self.inner.len() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> FusedIterator for IntoValues<K, V> {} </ins> #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a V)> {

assert_eq!(DROPS.load(Ordering::SeqCst), size); } } <ins> #[test] fn test_into_keys() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: BTreeMap<_, _> = vec.into_iter().collect(); let keys: Vec<_> = map.into_keys().collect(); assert_eq!(keys.len(), 3); assert!(keys.contains(&1)); assert!(keys.contains(&2)); assert!(keys.contains(&3)); } #[test] fn test_into_values() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: BTreeMap<_, _> = vec.into_iter().collect(); let values: Vec<_> = map.into_values().collect(); assert_eq!(values.len(), 3); assert!(values.contains(&'a')); assert!(values.contains(&'b')); assert!(values.contains(&'c')); } </ins>

#![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(map_first_last)] <ins> #![feature(map_into_keys_values)] </ins> #![feature(new_uninit)] #![feature(pattern)] #![feature(str_split_once)]

{ self.base.retain(f) } <ins> /// Creates a consuming iterator visiting all the keys in arbitrary order. /// The map cannot be used after calling this. /// The iterator element type is `K`. /// /// # Examples /// /// ``` /// #![feature(map_into_keys_values)] /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); /// map.insert("a", 1); /// map.insert("b", 2); /// map.insert("c", 3); /// /// let vec: Vec<&str> = map.into_keys().collect(); /// ``` #[inline] #[unstable(feature = "map_into_keys_values", issue = "75294")] pub fn into_keys(self) -> IntoKeys<K, V> { IntoKeys { inner: self.into_iter() } } /// Creates a consuming iterator visiting all the values in arbitrary order. /// The map cannot be used after calling this. /// The iterator element type is `V`. /// /// # Examples /// /// ``` /// #![feature(map_into_keys_values)] /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); /// map.insert("a", 1); /// map.insert("b", 2); /// map.insert("c", 3); /// /// let vec: Vec<i32> = map.into_values().collect(); /// ``` #[inline] #[unstable(feature = "map_into_keys_values", issue = "75294")] pub fn into_values(self) -> IntoValues<K, V> { IntoValues { inner: self.into_iter() } } </ins> } impl<K, V, S> HashMap<K, V, S>

inner: IterMut<'a, K, V>, } <ins> /// An owning iterator over the keys of a `HashMap`. /// /// This `struct` is created by the [`into_keys`] method on [`HashMap`]. /// See its documentation for more. /// /// [`into_keys`]: HashMap::into_keys #[unstable(feature = "map_into_keys_values", issue = "75294")] pub struct IntoKeys<K, V> { inner: IntoIter<K, V>, } /// An owning iterator over the values of a `HashMap`. /// /// This `struct` is created by the [`into_values`] method on [`HashMap`]. /// See its documentation for more. /// /// [`into_values`]: HashMap::into_values #[unstable(feature = "map_into_keys_values", issue = "75294")] pub struct IntoValues<K, V> { inner: IntoIter<K, V>, } </ins> /// A builder for computing where in a HashMap a key-value pair would be stored. /// /// See the [`HashMap::raw_entry_mut`] docs for usage examples.

} } <ins> #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> Iterator for IntoKeys<K, V> { type Item = K; #[inline] fn next(&mut self) -> Option<K> { self.inner.next().map(|(k, _)| k) } #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> ExactSizeIterator for IntoKeys<K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> FusedIterator for IntoKeys<K, V> {} #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K: Debug, V: Debug> fmt::Debug for IntoKeys<K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.inner.iter().map(|(k, _)| k)).finish() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> Iterator for IntoValues<K, V> { type Item = V; #[inline] fn next(&mut self) -> Option<V> { self.inner.next().map(|(_, v)| v) } #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> ExactSizeIterator for IntoValues<K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K, V> FusedIterator for IntoValues<K, V> {} #[unstable(feature = "map_into_keys_values", issue = "75294")] impl<K: Debug, V: Debug> fmt::Debug for IntoValues<K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.inner.iter().map(|(_, v)| v)).finish() } } </ins> #[stable(feature = "drain", since = "1.6.0")] impl<'a, K, V> Iterator for Drain<'a, K, V> { type Item = (K, V);

} #[test] <ins> fn test_into_keys() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: HashMap<_, _> = vec.into_iter().collect(); let keys: Vec<_> = map.into_keys().collect(); assert_eq!(keys.len(), 3); assert!(keys.contains(&1)); assert!(keys.contains(&2)); assert!(keys.contains(&3)); } #[test] fn test_into_values() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: HashMap<_, _> = vec.into_iter().collect(); let values: Vec<_> = map.into_values().collect(); assert_eq!(values.len(), 3); assert!(values.contains(&'a')); assert!(values.contains(&'b')); assert!(values.contains(&'c')); } #[test] </ins> fn test_find() { let mut m = HashMap::new(); assert!(m.get(&1).is_none());