I am trying to iterate on on Option<Vec<>>
.
#[derive(Debug)]
pub struct Person {
pub name: Option<String>,
pub age: Option<u64>,
}
#[derive(Debug)]
pub struct Foo {
pub people: Option<Vec<Person>>,
}
Naively I am using
for i in foo.people.iter() {
println!("{:?}", i);
}
Instead of iterating over all the elements of the Vec
, I am actually displaying the whole Vec
. It is like I am iterating over the only reference of the Option
.
Using the following, I am iterating over the Vec
content:
for i in foo.people.iter() {
for j in i.iter() {
println!("{:?}", j);
}
}
I am not sure this is the most pleasant syntax, I believe you should unwrap the Option
first to actually iterate on the collection.
Then I don't see where you can actually use Option::iter
, if you always have a single reference.
Here is the link to the playground.
As mentioned in comments to another answer, I would use the following:
// Either one works
foo.people.iter().flatten()
foo.people.iter().flat_map(identity)
The iter
method on Option<T>
will return an iterator of one or zero elements.
flatten
takes each element (in this case &Vec<Person>
) and flattens their nested elements.
This is the same as doing flat_map
with identity
, which takes each element (in this case &Vec<Person>
) and flattens their nested elements.
Both paths result in an Iterator<Item = &Person>
.
Option
has an iter
method that "iterates over the possibly contained value", i.e. provides either the single value in the Option
(if option is Some
), or no values at all (if the option is None
). As such it is useful if you want to treat the option as a container where None
means the container is empty and Some
means it contains a single element.
To iterate over the underlying element's values, you need to switch from foo.people.iter()
to either foo.people.unwrap().iter()
or foo.people.unwrap_or_else(Vec::new).iter()
, depending on whether you want the program to panic or to not iterate when encountering None
people.
Compilable example in the playground.
Use Option::as_deref
and Option::unwrap_or_default
:
for i in foo.people.as_deref().unwrap_or_default() {
println!("{:?}", i);
}
Option::as_deref
converts &Option<Vec<T>>
into Option<&[T]>
, then unwrap_or_default
returns that &[T]
or the default (an empty slice). You can then iterate on that directly.
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With