Home > Back-end >  How to join the two Options<Vec<String>>
How to join the two Options<Vec<String>>

Time:11-09

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.

Rust Playground

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
};

Playground

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.

  • Related