1

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?

1 Answer 1

2

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)}); } } } 
Sign up to request clarification or add additional context in comments.

2 Comments

This worked well. I was even able to simplify this by not using the extra crate: if let Some(idx) = bVec.iter().position(|b| b.n==42) {
@jeevcat Good catch!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.