Collect fixed sized array from iterator

#1

Hello everybody,

I’m wondering how to collect a fixed-sized array from an iterator.

Using vectors as return type works:

fn main() {
    
    let array = [1, 2, 3];
    let rev :  Vec<_> = array.into_iter().rev().map(|x| *x).collect();    
    println!("{:#?}", rev)
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8ea4f57442035371debe97accbc155e9

How to obtain a fixed size array ( like [_,3]) instead?
Ideally without copying the data or using boxed slices (https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_boxed_slice).

Given the fact that iterators are considered a zero-cost abstraction there must be a way to stay with static dispatching.
Thanks!

#2

You can’t do this with the built-in array type, but you can make use of arrayvec:

fn main() {
    let array = [1, 2, 3];
    let rev: ArrayVec<[_; 3]> = array.into_iter().rev().map(|x| *x).collect();
    println!("{:#?}", rev);
   // if you want to drop the AV, and get the array out:
   // let array = rev.into_inner().unwrap();
}
2 Likes
#3

Thanks for the answer.

I had a look at arrayvec before and the into_inner function comes with a performance note as well:

https://docs.rs/arrayvec/0.4.10/arrayvec/struct.ArrayVec.html#method.into_inner

I assume there is some kind of copy involved as well?

#4

ArrayVec::into_inner() moves out the whole array from itself, and in Rust move is semantically equal to memcpy, so theorically it can memcpy HUGE array out. But llvm can optimize out most of unnecessary memcpy so practically such move out is considered near zero cost.

1 Like