How do I initialize a Vec with a closure?

Hi! I am trying to initialize a Vec with random value. What is the idiomatic Rust way to do it? So far, I think it's:

let values: Vec<u8> = (0..count).map(|_| rng.gen_range(0, 10)).collect();

But I find it harder to read than needed. I was expecting something more like:

let values: Vec<u8> = Vec::initialize_with(count, || rng.gen_range(0, 10));

How about this?

let mut values = vec![0_u8; count];
rng.fill_bytes(&mut values);

There's also repeat_with():

let values: Vec<_> = iter::repeat_with(|| rng.gen_range(0, 10)).take(count).collect();

or if you really don't like collect() and insist on using Vec's methods directly:

let values = Vec::from_iter(iter::repeat_with(|| rng.gen_range(0, 10)).take(count));

That looks like the code I'd write to do this. If you had a single value to fill it with, you could use vec![value; count], but that won't rerun the code for each value.

Looking at the code, I think I might actually prefer the first to your second hypothetical. It is less direct, but it tells the reader exactly what's happening - and it makes it 100% clear that gen_range is called count times, not just once, and it uses individual pieces which everyone who's used iterators will recognize.

With that in mind, I looked through the rand documentation, and found something which could be better:

let v: Vec<_> = rng.sample_iter(Uniform::new(0, 10)).take(count).collect();

Not 100% sure if this is actually better, though.

I think this code will fill with fully random values, whereas the OP has each byte only taking on values 0-10?

You're right, I missed that.

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