case 1.
v1 = None
v2 = Some(vec[..])
result = Some(vec[..])
case 2.
v1 = Some(vec[..])
v2 = None
result = Some(vec[..])
case 3.
v1 = Some(vec[..])
v2 = Some(vec[..])
result = Some(vec[..])
case 4.
v1 = None
v2 = None
result = None
Is there a generalized way to implement this?
CodePudding user response:
You can take advantage of the fact that Options can be converted to Iterators and use Iterator::reduce:
v1.into_iter()
.chain(v2.into_iter())
.reduce(|mut v1, mut v2| {
v1.append(&mut v2);
v1
})
Chaining the two Option iterators will give us an iterator that yields either 0 (if both v1 and v2 were None), 1 (if either v1 or v2 was None), or 2 (if both v1 and v2 were not None) vectors. Iterator::reduce will only "reduce" the iterator with the closure if there are 2 or more vectors in the iterator and otherwise will return the only vector, if any, in the iterator.
CodePudding user response:
You can just use a match statement representing your cases:
let result = match (v1, v2) {
(res@Some(_), None) => res,
(None, res@Some(_)) => res,
(Some(r1), Some(r2)) => Some(r1.into_iter().chain(r2).collect()),
_ => None
};
CodePudding user response:
Yes! The Option<T> enum implements the map method. And really a whole bunch of other iterator related methods.
The map function takes your Option<T> and turns it into an Option<U> based on the closure you provide to map. None gets mapped to None, and Some(el) gets mapped to Some(closure_applied_to_el).
Here's how that can look like in your case:
pub fn join_vecs<T>(v1: Option<Vec<T>>, v2: Option<Vec<T>>) -> Option<Vec<T>> {
v1.map(|mut el| {el.extend(v2.into_iter().flatten()); el})
}
pub fn main() {
let v1 = vec![1,2,3];
let v1 = Some(v1);
let v2 = vec![42, 55, 69];
let v2 = Some(v2);
let res = join_vecs(v1, v2);
println!("{:?}", res);
}
Note, my version takes ownership. Fiddle around with the arguments and with iter instead if that's not what you want.
