How do I create a Vec from a range and shuffle it?
Solution 1
Rand v0.6.0
The Rng::shuffle
method is now deprecated; rand::seq::SliceRandom
trait should be used. It provides the shuffle()
method on all slices, which accepts an Rng
instance:
// Rust edition 2018 no longer needs extern crate
use rand::thread_rng;
use rand::seq::SliceRandom;
fn main() {
let mut vec: Vec<u32> = (0..10).collect();
vec.shuffle(&mut thread_rng());
println!("{:?}", vec);
}
See it on Playground.
Original answer
You're very close. This should work:
extern crate rand;
use rand::{thread_rng, Rng};
fn main() {
let mut vec: Vec<u32> = (0..10).collect();
let slice: &mut [u32] = &mut vec;
thread_rng().shuffle(slice);
}
&mut [T]
is implicitly coercible to &[T]
, and you annotated the slice
variable with &[u32]
, so the slice became immutable: &mut [u32]
was coerced to &[u32]
. mut
on the variable is not relevant here because slices are just borrows into data owned by someone else, so they do not have inherited mutability - their mutability is encoded in their types.
In fact, you don't need an annotation on slice
at all. This works as well:
extern crate rand;
use rand::{thread_rng, Rng};
fn main() {
let mut vec: Vec<u32> = (0..10).collect();
let slice = vec.as_mut_slice();
thread_rng().shuffle(slice);
}
You don't even need the intermediate variable:
extern crate rand;
use rand::{thread_rng, Rng};
fn main() {
let mut vec: Vec<u32> = (0..10).collect();
thread_rng().shuffle(&mut vec);
}
You should read The Rust Programming Language as it explains the concepts of ownership and borrowing and how they interact with mutability.
Solution 2
You can use shuffle
like this:
extern crate rand;
use rand::Rng;
fn main() {
let mut vec: Vec<usize> = (0..10).collect();
println!("{:?}", vec);
rand::thread_rng().shuffle(&mut vec);
println!("{:?}", vec);
}
le_me
Updated on March 26, 2020Comments
-
le_me about 4 years
I have the following code:
extern crate rand; use rand::{thread_rng, Rng}; fn main() { let mut vec: Vec<u32> = (0..10).collect(); let mut slice: &[u32] = vec.as_mut_slice(); thread_rng().shuffle(slice); }
and get the following error:
error[E0308]: mismatched types --> src/main.rs:9:26 | 9 | thread_rng().shuffle(slice); | ^^^^^ types differ in mutability | = note: expected type `&mut [_]` found type `&[u32]`
I think I understand that the content of vectors and slices is immutable and that causes the error here, but I'm unsure.
The signature of
as_mut_slice
ispub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T]
, so the slice should be mutable, but it somehow isn't.I know that there must be an easy fix, but I tried my best and couldn't get it to work.
-
J-L over 5 yearsThank you for your answer. Unfortunately, I pasted your code into the Rust Playground (play.rust-lang.org) and discovered that
thread_rng().shuffle
is now deprecated. Do you know how we're supposed to shuffle a vector now? (I think we're supposed to use a trait, but I'm not experienced enough in Rust to know how to do that yet.) -
J-L over 5 yearsThank you for your answer. Unfortunately, I pasted your code into the Rust Playground (play.rust-lang.org) and discovered that
thread_rng().shuffle
is now deprecated. Do you know how we're supposed to shuffle a vector now? (I think we're supposed to use a trait, but I'm not experienced enough in Rust to know how to do that yet.) -
Akavall over 5 years@J-L, I see. Thanks. I tried to do it the other way: play.rust-lang.org/…, but I am getting different warnings, not sure if this is a better solution.