Think about HashMap
Struct std::collections::HashMap
pub fn insert(&mut self, k: K, v: V) -> Option<V>
Inserts a key-value pair into the map.
pub fn keys(&self) -> Keys<K, V>[src]
An iterator visiting all keys in arbitrary order. The iterator element type is &'a K.
As a straight application of insert
, the following code seems to work well.
// collect keys of a HashMap into a Vec
let h: HashMap<K, V>;
let v: Vec<_> = h.keys().collect();
But in some case this is troublesome. For example,
// key is String
let h: HashMap<String, V>;
return h.keys().collect::<Vec<String>>();
is a type mismatch because the return type of keys
is the reference to key:
error[E0277]: a collection of type `std::vec::Vec<std::string::String>` cannot be built from an iterator over elements of type `&std::string::String`
To fix it, make hash
hold &String
as key:
// change the key's type
let h: HashMap<&String, V>;
return h.keys().collect::<Vec<&String>>();
it emits another error in this case:
error[E0515]: cannot return value referencing local variable `h`
How about dereferencing and injecting them to the return value?
// &String to String
let h: HashMap<&String, V>;
let v: Vec<String> = h.keys().map(|k| *k).collect();
It can't work (we can't destruct data in order to make a return value):
error[E0507]: cannot move out of borrowed content
So we need to copy them explicitly, if K
doesn't have Copy
trait.
let hash: HashMap<String, V>;
return hash.keys().map(|k| k.to_string()).collect::<Vec<String>>();
But this code may contain unwanted memory copy. So make hash
hold the reference.
// `hash` points the original data to avoid double allocation
let hash: HashMap<&String, V>;
return hash.keys().map(|k| k.to_string()).collect::<Vec<String>>();
That's it.