Look into reservoir sampling: https://en.m.wikipedia.org/wiki/Reservoir_sampling Answer from hippyup on reddit.com
🌐
Reddit
reddit.com › r/rust › what's the best way to shuffle an iterator?
r/rust on Reddit: What's the best way to shuffle an iterator?
April 7, 2023 -

I need to get some random distinct elements inside a range. I don't need to shuffle all the items, so collecting the iterator into a `vec` and calling the ` shuffle` method on it is not desirable. Is there a way to iterate over the range in random order and only get the first `n` items?

EDIT with some context:
I have arbitrarily large collections of `BigInt` numbers and I need to retrieve `n` values in a range from `0` to numbers even of hundreds or thousands of bits. I cannot collect 1 googol items in a `Vec` only to retrieve some tenths or hundreds values. Of course, I could assume that the probability of getting the same number twice is negligible in this specific case but, since the range is arbitrary large I could also have a range of 10 numbers and I must take 9 of them. As a general solution I have started getting random numbers in the target range and manually check if this has been already taken in a previous iteration but I was looking for a lazy solution that could avoid unnecessary checks or allocations.

Top answer
1 of 3
133

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.


2 of 3
20

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);
}
Discussions

Shuffling object vectors around
I guess this is a trivial one but I have no idea how to make it work. So I wanna save space and thus not make any extra copies of anything if I do not need to. I wanna switch the content of two vectors in my object through a private method. The example below i am showing is an oversimplification ... More on users.rust-lang.org
🌐 users.rust-lang.org
1
0
February 18, 2020
Shuffle Iterator
Background What is your motivation? In a game AI, I'd like to use a random permutation of a vector. However, the order is only used in an iterator and discarded afterwards. Feature request I... More on github.com
🌐 github.com
5
June 17, 2019
java - How to iterate over an enum, insert it into a vector, then shuffle it in Rust? - Stack Overflow
I'm writing code to initialize a deck with 52 cards and shuffle them. In Java, I use an ArrayList and iterate through the Suit enum and the Rank enum, adding a Card(suit,rank) object as I go along. I then use Collections.shuffle(). I am trying to port this code to Rust, using vectors and structs. More on stackoverflow.com
🌐 stackoverflow.com
September 10, 2019
Appropriate name for single vector shuffle
Shuffles for single vectors are currently called permute! (when the indices are compile-time constants) and permute_dyn (when the indices are provided with a run-time vector of the same vector size). These shuffles are allowed to repeat ... More on github.com
🌐 github.com
4
August 29, 2018
🌐
Rust Programming Language
users.rust-lang.org › help
[Solved] Efficient rust random shuffle of? - help - The Rust Programming Language Forum
February 20, 2019 - - Stack Overflow extern crate rand; use rand::{thread_rng, Rng}; fn main() { let mut vec: Vec = (0..10).collect(); let slice: &mut [u32] = &mut vec; thread_rng().shuffle(slice); } My question is: I'm doing this on a Vec with 300_000_000 entries.
🌐
Rust
docs.rs › shuffle › latest › shuffle
shuffle - Rust
use shuffle::shuffler::Shuffler; use shuffle::irs::Irs; use rand::rngs::mock::StepRng; let mut rng = StepRng::new(2, 13); let mut irs = Irs::default(); let mut input = vec![1, 2, 3, 4, 5]; irs.shuffle(&mut input, &mut rng); assert_eq!(&input, &[4, 1, 5, 3, 2]);
🌐
Programming Idioms
programming-idioms.org › idiom › 10 › shuffle-a-list › 410 › rust
Shuffle a list, in Rust
Rust · use std::hash::{BuildHasher, Hasher, RandomState}; pub fn shuffle<T>(vec: &mut [T]) { let n = vec.len(); for i in 0..(n - 1) { let j = rand() % (n - i) + i; vec.swap(i, j); } } pub fn rand() -> usize { RandomState::new().build_hasher().finish() as usize } C · Clojure · C++ C# C# D · Dart · Dart · Elixir · Erlang · Fortran · Go · Go · Go · Go · Go · Groovy · Haskell · JS · Java ·
🌐
Rust
docs.rs › shuffle
Crate shuffle - Rust
use shuffle::shuffler::Shuffler; use shuffle::irs::Irs; use rand::rngs::mock::StepRng; let mut rng = StepRng::new(2, 13); let mut irs = Irs::default(); let mut input = vec![1, 2, 3, 4, 5]; irs.shuffle(&mut input, &mut rng); assert_eq!(&input, &[4, 1, 5, 3, 2]);
🌐
Rust
docs.rs › nois › latest › nois › fn.shuffle.html
shuffle in nois - Rust
use nois::{randomness_from_str, shuffle}; let randomness = randomness_from_str("9e8e26615f51552aa3b18b6f0bcf0dae5afbe30321e8d7ea7fa51ebeb1d8fe62").unwrap(); let original = vec![ "bob".to_string(), "mary".to_string(), "su".to_string(), "marc".to_string() ]; let shuffled = shuffle(randomness, original.clone()); // The length of the vector is the same but the order of the elements has changed assert_eq!(shuffled.len(), original.len()); assert_ne!(shuffled, original);
Find elsewhere
🌐
crates.io
crates.io › crates › shuffle
shuffle - crates.io: Rust Package Registry
Implementation of various shuffling algorithms over slices.
🌐
GitHub
github.com › rust-random › rand › issues › 826
Shuffle Iterator · Issue #826 · rust-random/rand
June 17, 2019 - Background What is your motivation? In a game AI, I'd like to use a random permutation of a vector. However, the order is only used in an iterator and discarded afterwards. Feature request I'd like to have a struct RandomizedOrder tha...
Author   ThomasdenH
🌐
The Rust Programming Language
rust-lang.github.io › packed_simd › src › packed_simd_2 › api › shuffle.rs.html
shuffle.rs - source
/// # } /// ``` #[macro_export] macro_rules! shuffle { ($vec0:expr, $vec1:expr, [$l0:expr, $l1:expr]) => {{ #[allow(unused_unsafe)] unsafe { $crate::Simd($crate::__shuffle_vector2::<{[$l0, $l1]}, _, _>( $vec0.0, $vec1.0, )) } }}; ($vec0:expr, $vec1:expr, [$l0:expr, $l1:expr, $l2:expr, $l3:expr]) => {{ #[allow(unused_unsafe)] unsafe { $crate::Simd($crate::__shuffle_vector4::<{[$l0, $l1, $l2, $l3]}, _, _>( $vec0.0, $vec1.0, )) } }}; ($vec0:expr, $vec1:expr, [$l0:expr, $l1:expr, $l2:expr, $l3:expr, $l4:expr, $l5:expr, $l6:expr, $l7:expr]) => {{ #[allow(unused_unsafe)] unsafe { $crate::Simd($crate
🌐
The Rust Programming Language
rust-lang.github.io › packed_simd › packed_simd_2 › macro.shuffle.html
shuffle in packed_simd_2 - Rust
... // Shuffle allows reordering the elements: let x = i32x4::new(1, 2, 3, 4); let y = i32x4::new(5, 6, 7, 8); let r = shuffle!(x, y, [4, 0, 5, 1]); assert_eq!(r, i32x4::new(5, 1, 6, 2)); // The resulting vector can als be smaller than the input: let r = shuffle!(x, y, [1, 6]); assert_eq!(r, ...
🌐
Rust Rand
rust-random.github.io › book › guide-seq.html
Sequences - The Rust Rand Book
SliceRandom::partial_shuffle: partial shuffle; useful to extract amount random elements in random order
🌐
GitHub
github.com › rust-lang-nursery › packed_simd › issues › 102
Appropriate name for single vector shuffle · Issue #102 · rust-lang/packed_simd
August 29, 2018 - Shuffles for single vectors are currently called permute! (when the indices are compile-time constants) and permute_dyn (when the indices are provided with a run-time vector of the same vector size). These shuffles are allowed to repeat ...
Author   gnzlbg
🌐
Rust Programming Language
users.rust-lang.org › t › how-can-i-using-stable-rust-mutably-iterate-over-a-random-shuffle › 105457
How can I, using stable rust, mutably iterate over a random shuffle? - The Rust Programming Language Forum
January 17, 2024 - This is a follow up to a previous question. I ended up taking the previous solution and updating it to use Rayon for parallel computation. The code now looks like this all_orgs.par_chunks_mut(48).for_each(|chunk: &mut [Organism]|{ for i in 0 .. chunk.len() { let (left, others) = chunk.split_at_mut(i); let (middle, right) = others.split_at_mut(1); let org1 = &mut middle[0]; //process left for org2 in left { single_match_up(org1, org2); ...
🌐
Javaer101
javaer101.com › en › article › 12217283.html
How do I create a Vec from a range and shuffle it? - Javaer101
October 21, 2020 - 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); }