Ecumene
Ecumene

Reputation: 97

How do I interleave two Rust vectors by chunks of threes into a new vector?

I need an idiomatic way to interlace these two vectors:

let v1 = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let v2 = vec![7.0, 8.0, 9.0, 10.0, 11.0, 12.0];

The output I expect is:

[1.0, 2.0, 3.0,
 7.0, 8.0, 9.0,
 4.0, 5.0, 6.0,
 10.0, 11.0, 12.0];

I used itertools chunks method, but I don't believe this is the best implementation because there are two collect calls.

let output = interleave(&v1.into_iter().chunks(3), &v2.into_iter().chunks(3)).map(|v| {v.into_iter().collect::<Vec<f32>>()}).flatten().collect::<Vec<f32>>();

Is there a better way to write this iterator using itertools?

Upvotes: 2

Views: 2709

Answers (2)

justinas
justinas

Reputation: 6857

Seems like the same can be achieved with only std:

fn main() {
    let v1 = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
    let v2 = vec![7.0, 8.0, 9.0, 10.0, 11.0, 12.0];

    let v3: Vec<f64> = v1.chunks(3)
        .zip(v2.chunks(3)) // yields items like (&[1.0, 2.0, 3.0], &[7.0, 8.0, 9.0])
        .flat_map(|(a, b)| a.into_iter().chain(b)) // chains to produce iterators like [1.0, 2.0, 3.0, 7.0, 8.0, 9.0]
        .copied() // &f64 -> f64, optional
        .collect();

    println!("v3 is {:?}", v3);
}

I.e. zip -> chain acts like interleave.

Upvotes: 8

edwardw
edwardw

Reputation: 13942

You want Iterator::flatten:

use itertools::interleave;

fn main() {
    let v1 = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
    let v2 = vec![7.0, 8.0, 9.0, 10.0, 11.0, 12.0];
    let v = interleave(v1.chunks(3), v2.chunks(3))
        .flatten()
        .collect::<Vec<_>>();
    dbg!(v);
}

Upvotes: 7

Related Questions