ynn
ynn

Reputation: 4895

Clean way to collect into matrix

I'd like to split and collect this strangely-shaped vector

let v = vec![
    0, 1, 2, 3,
    4, 5, 6, 7,

    8, 9,
    10, 11,
    12, 13,
];

into these two matrices:

let v1 = vec![
    vec![0, 1, 2, 3],
    vec![4, 5, 6, 7],
];

let v2 = vec![
    vec![8, 9],
    vec![10, 11],
    vec![12, 13],
];

(The elements are sequential (i.e. 1, 2, 3, ...) but this is just for example. Also, though the number of matrices are two here, this number is just for example; sometimes it should be three or more.)

Trivially it is possible (Rust Playground):

let mut v1: Vec<Vec<usize>> = vec![];
for i in 0..2 {
    v1.push(v.iter().skip(i * 4).take(4).copied().collect());
}

let mut v2: Vec<Vec<usize>> = vec![];
for i in 0..3 {
    v2.push(v.iter().skip(8 + i * 2).take(2).copied().collect());
}

But, is there a cleaner way? Here's the pseudo code I want:

let v1 = v.iter().every(4).take(2).collect();
let v2 = v.iter().skip(8).every(2).take(3).collect();

Upvotes: 3

Views: 90

Answers (2)

ynn
ynn

Reputation: 4895

If an external crate is allowed, you can use Itertools::chunks:

v.iter().chunks(4).into_iter().take(2).map(|l| l.copied().collect_vec()).collect()

(Rust Playground)

Upvotes: 3

Mac O&#39;Brien
Mac O&#39;Brien

Reputation: 2907

You can split the initial vector into two slices and iterate each of them separately (playground):

let (left, right) = v.split_at(8);
    
let v1 = left.chunks(4).map(|s| s.to_vec()).collect::<Vec<_>>();
let v2 = right.chunks(2).map(|s| s.to_vec()).collect::<Vec<_>>();

Upvotes: 4

Related Questions