0

I want to combine two reference vectors and convert them into a vector of values without consuming an iterator.

Situation:

Generate vectors by iterating over specific combinations. (2 elements from one vector, 2 elements from another vector)

  • Code:
use core::iter::Iterator;
use itertools::Itertools;

fn main() {
    let vec_a: Vec<u8> = vec![1, 2, 3];
    let vec_b: Vec<u8> = vec![4, 5, 6];

    // a: Vec<&u8>
    for a in vec_a.iter().combinations(2) {
        // b: Vec<&u8>
        for b in vec_b.iter().combinations(2) {
            // c: Vec<u8> <- a + b
            let c: Vec<u8> = a.clone().into_iter().chain(b).cloned().collect();
            println!("a: {:?}, b: {:?}, c: {:?}", a, b, c);
        }
    }
}

  • Expected output:
a: [1, 2], b: [4, 5], c: [1, 2, 4, 5]
a: [1, 2], b: [4, 6], c: [1, 2, 4, 6]
a: [1, 2], b: [5, 6], c: [1, 2, 5, 6]
a: [1, 3], b: [4, 5], c: [1, 3, 4, 5]
a: [1, 3], b: [4, 6], c: [1, 3, 4, 6]
a: [1, 3], b: [5, 6], c: [1, 3, 5, 6]
a: [2, 3], b: [4, 5], c: [2, 3, 4, 5]
a: [2, 3], b: [4, 6], c: [2, 3, 4, 6]
a: [2, 3], b: [5, 6], c: [2, 3, 5, 6]

P.S.

I read the following link before posting my question. However, the answer to this question consumes Vec and its iterator, so it did not work in this situation.

Best way to concatenate vectors in Rust

Azriel 1rf
  • 79
  • 9
  • Do you actually want *all* combinations of the two vecs? Your current code produces a subset of possible combinations. – harmic Apr 28 '22 at 05:37
  • I've already read the duplicate link and best answer and 2nd best one does not work in this situation... – Azriel 1rf Apr 28 '22 at 05:57
  • @Dogbert It seems not working. https://gist.github.com/azriel1rf/c5521940d470d612b2d9e85d0e1c197d – Azriel 1rf Apr 28 '22 at 06:04
  • 2
    @Azriel1rf try `sub_a.iter().cloned().chain(sub_b).cloned().collect()` – Dogbert Apr 28 '22 at 06:17
  • @Dogbert Thanks, it worked. Is `iter().cloned()` more efficient than `clone().into_iter()`, right? – Azriel 1rf Apr 28 '22 at 06:32
  • 1
    @Azriel1rf Yes it is (it doesn't clone the vector, only on the fly). But do you need to consume `A` or `B` (or both)? Currently you consume `B` but not `A`. – Chayim Friedman Apr 28 '22 at 09:41
  • 1
    What do you mean y "when using a double loop"? Anyway, what I had in mind was something like `A.iter().chain(&B).copied().copied()` – Chayim Friedman Apr 28 '22 at 10:09
  • @ChayimFriedman Thank you so much. I got it. If both are consumed, the code is as follows? `A.into_iter().chain(B).cloned().collect()` – Azriel 1rf Apr 28 '22 at 10:45
  • 1
    @Azriel1rf Yes (you can replace `cloned()` with `copied()`). – Chayim Friedman Apr 28 '22 at 10:46
  • @ChayimFriedman I got it. The `copy` is better than `clone` in this situation. https://stackoverflow.com/questions/31012923/what-is-the-difference-between-copy-and-clone – Azriel 1rf Apr 28 '22 at 10:48
  • 1
    @Azriel1rf I expect both to be optimized to the same machine code, but I prefer `copied()` because it's more explicit (and may, though rarely, be faster). – Chayim Friedman Apr 28 '22 at 10:49

1 Answers1

1

Thanks to @ChayimFriedman.

There are some ways to do this.

  • Without consumption

    // a: Vec<&u8>
    // b: Vec<&u8>
    
    let c: Vec<u8> = a.iter().chain(&b).copied().copied().collect();
    println!("a: {:?}", a);
    println!("b: {:?}", b);
    
  • With consumption

    // a: Vec<&u8>
    // b: Vec<&u8>
    
    let c: Vec<u8> = a.into_iter().chain(b).copied().collect();
    // println!("a: {:?}", a); -> compile error
    // println!("b: {:?}", b); -> compile error
    
Azriel 1rf
  • 79
  • 9