Take the following data type:
let mut items = HashMap::<u64, HashMap<u64, bool>>::new();
I successfully managed to turn it into a vector of tuples like this:
let mut vector_of_tuples: Vec<(u64, u64, bool)> = vec![];
for (outer_id, inner_hash_map) in items.iter() {
for (inner_id, state) in inner_hash_map.iter() {
vector_of_tuples.push((*outer_id, *inner_id, *state));
}
}
But I want to shrink this code logic, possibly with the help of the Map and Zip functions from the Rust standard library.
How can I achieve the same result without using for loops?
How can I achieve the same result without using for loops?
You can use collect()
to build a vector from an iterator without an explicit loop:
let vector_of_tuples: Vec<(u64, u64, bool)> = items
.iter()
// ...
.collect();
To expand the contents of the inner hash maps into the iterator, you can use flat_map
:
let vector_of_tuples: Vec<_> = items
.iter()
.flat_map(|(&outer_id, inner_hash_map)| {
inner_hash_map
.iter()
.map(move |(&inner_id, &state)| (outer_id, inner_id, state))
})
.collect();
In many cases chaining iterator adapters will yield more understandable code than the equivalent for
loop because iterators are written in a declarative style and tend not to require side effects. However, in this particular case the original for
loop might actually be the more readable option. YMMV, the best option will sometimes depend on the programming background of you and other project contributors.