jeevcat
jeevcat

Reputation: 363

Rust: Map two Vecs into a third Vec of composite structs

I have three structs:

struct A;

struct B;

struct C {
    a: Option<A>,
    b: Option<B>
}

Given inputs Vec<A> and Vec<B> and some predicate function, I want to create an output Vec<C>, which is a combination of the elements of the inputs, something like the following:

let aVec: Vec<A> = vec![];
let bVec: Vec<B> = vec![];
let mut cVec: Vec<C> = vec![];
for a in aVec {
    if let Some(b) = bVec.into_iter().find(predicate) {
        cVec.push(C{a: Some(a), b: Some(b)});
    }
}

Is there a way to do this without needing B to be copyable? Both input vectors aren't required after the operation. Also, is this possible without the loop?

Upvotes: 1

Views: 275

Answers (1)

phimuemue
phimuemue

Reputation: 36071

You can:

  • Find the index of the element satisfying predicate. (I would use Iterator::position.)
  • remove or swap_remove the element at the position obtained by the previous step.
  • push the previously removed element into result.

In code:

use itertools; // 0.8.2
use itertools::Itertools;

struct A {}

struct B {
    n: usize,
}

struct C {
    a: Option<A>,
    b: Option<B>
}

fn  main() {
    let aVec: Vec<A> = vec![];
    let mut bVec: Vec<B> = vec![];
    let mut cVec: Vec<C> = vec![];
    for a in aVec {
        if let Some(idx) = bVec.iter()
                               .position(|b| b.n==42)
        {
            let b = bVec.remove(idx); // or swap_remove if ordering does not need to be preserved
            cVec.push(C{a: Some(a), b: Some(b)});
        }

    }    
}

Upvotes: 2

Related Questions