Collect/Concatenate collection of [T;N] into Vec<T>

I can't seem to figure out how to do this with concat but I have come up with these two solutions.
How would you do it?

fn get_item(i: u8) -> [u8; 4] {
    [i, i, i, i]

fn main() {
    let r: Vec<u8> = Vec::new();

    let v1 = (0..10).map(get_item).fold(r, |mut acc, x| {
    // Or
    let v2 = (0..10)
        .flat_map(|c| c.iter().map(|c| *c).collect::<Vec<u8>>())

I was trying to use flat_map without intermediate allocation but couldn't get it work either:

// Does not compile
    let v3 = (0..10)
        .flat_map(|c| c.iter().map(|c| *c))

Playground link

It's a quirk of arrays not supporting into_iter(). They only have .iter() which borrows them. In Rust a borrow can't exist without an owned value having a permanent storage somewhere at the same time. The problem is that flat_map() makes a new c only temporarily for the callback, tries to return c.iter(), and immediately destroy c afterwards, so iter() borrowing the about-to-be-destroyed c can't exist.

If it was into_iter(), then the c value would live in the iterator, so it'd be returned with it, instead of being destroyed after the callback.

Thank you, I understand the lifetime issue in flat_map.
I guess I am trying to avoid one allocation in flat_map and another when doing final collect, which may not be possible?

What are other solutions to achieving this with/without iterators & adapters?

You can implement your own into_iter()-like iterator that wraps [T; N] and returns T, and it all will just work fine.

A basic loop like this is optimal:

let mut r = Vec::with_capacity(10*4);

for i in (0..10) {
   let t = get_item(i);
1 Like

Hmmm, didn't know about Copied. Very interesting & seems it was just added recently (1.36)

Thanks for your help :slight_smile:


This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.