Trait IndexedRandom

pub trait IndexedRandom: Index<usize>

Extension trait on indexable lists, providing random sampling methods.

This trait is implemented on [T] slice types. Other types supporting [std::ops::Index<usize>] may implement this (only Self::len must be specified).

Required Methods

fn len(&self) -> usize

The length

Provided Methods

fn is_empty(&self) -> bool

True when the length is zero

fn choose<R>(&self, rng: &mut R) -> Option<&Self::Output>
where
    R: Rng + ?Sized,

Uniformly sample one element

Returns a reference to one uniformly-sampled random element of the slice, or None if the slice is empty.

For slices, complexity is O(1).

Example

use rand::seq::IndexedRandom;

let choices = [1, 2, 4, 8, 16, 32];
let mut rng = rand::rng();
println!("{:?}", choices.choose(&mut rng));
assert_eq!(choices[..0].choose(&mut rng), None);
fn choose_iter<R>(&self, rng: &mut R) -> Option<impl Iterator<Item = &Self::Output>>
where
    R: Rng + ?Sized,

Return an iterator which samples from self with replacement

Returns None if and only if self.is_empty().

Example

use rand::seq::IndexedRandom;

let choices = [1, 2, 4, 8, 16, 32];
let mut rng = rand::rng();
for choice in choices.choose_iter(&mut rng).unwrap().take(3) {
    println!("{:?}", choice);
}
fn sample<R>(&self, rng: &mut R, amount: usize) -> IndexedSamples<'_, Self, Self::Output>
where
    Self::Output: Sized,
    R: Rng + ?Sized,

Uniformly sample amount distinct elements from self

Chooses amount elements from the slice at random, without repetition, and in random order. The returned iterator is appropriate both for collection into a Vec and filling an existing buffer (see example).

In case this API is not sufficiently flexible, use index::sample.

For slices, complexity is the same as index::sample.

Example

use rand::seq::IndexedRandom;

let mut rng = &mut rand::rng();
let sample = "Hello, audience!".as_bytes();

// collect the results into a vector:
let v: Vec<u8> = sample.sample(&mut rng, 3).cloned().collect();

// store in a buffer:
let mut buf = [0u8; 5];
for (b, slot) in sample.sample(&mut rng, buf.len()).zip(buf.iter_mut()) {
    *slot = *b;
}
fn sample_array<R, const N: usize>(&self, rng: &mut R) -> Option<[Self::Output; N]>
where
    Self::Output: Clone + Sized,
    R: Rng + ?Sized,

Uniformly sample a fixed-size array of distinct elements from self

Chooses N elements from the slice at random, without repetition, and in random order.

For slices, complexity is the same as index::sample_array.

Example

use rand::seq::IndexedRandom;

let mut rng = &mut rand::rng();
let sample = "Hello, audience!".as_bytes();

let a: [u8; 3] = sample.sample_array(&mut rng).unwrap();
fn choose_weighted<R, F, B, X>(&self, rng: &mut R, weight: F) -> Result<&Self::Output, WeightError>
where
    R: Rng + ?Sized,
    F: Fn(&Self::Output) -> B,
    B: SampleBorrow<X>,
    X: SampleUniform + Weight + PartialOrd<X>,

Biased sampling for one element

Returns a reference to one element of the slice, sampled according to the provided weights.

The specified function weight maps each item x to a relative likelihood weight(x). The probability of each item being selected is therefore weight(x) / s, where s is the sum of all weight(x).

For slices of length n, complexity is O(n). For more information about the underlying algorithm, see the WeightedIndex distribution.

See also choose_weighted_mut.

Example

use rand::prelude::*;

let choices = [('a', 2), ('b', 1), ('c', 1), ('d', 0)];
let mut rng = rand::rng();
// 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c',
// and 'd' will never be printed
println!("{:?}", choices.choose_weighted(&mut rng, |item| item.1).unwrap().0);
fn choose_weighted_iter<R, F, B, X>(&self, rng: &mut R, weight: F) -> Result<impl Iterator<Item = &Self::Output>, WeightError>
where
    R: Rng + ?Sized,
    F: Fn(&Self::Output) -> B,
    B: SampleBorrow<X>,
    X: SampleUniform + Weight + PartialOrd<X>,

Biased sampling with replacement

Returns an iterator which samples elements from self according to the given weights with replacement (i.e. elements may be repeated).

See also doc for Self::choose_weighted.

fn sample_weighted<R, F, X>(&self, rng: &mut R, amount: usize, weight: F) -> Result<IndexedSamples<'_, Self, Self::Output>, WeightError>
where
    Self::Output: Sized,
    R: Rng + ?Sized,
    F: Fn(&Self::Output) -> X,
    X: Into<f64>,

Biased sampling of amount distinct elements

Similar to sample, but where the likelihood of each element's inclusion in the output may be specified. Zero-weighted elements are never returned; the result may therefore contain fewer elements than amount even when self.len() >= amount. The elements are returned in an arbitrary, unspecified order.

The specified function weight maps each item x to a relative likelihood weight(x). The probability of each item being selected is therefore weight(x) / s, where s is the sum of all weight(x).

This implementation uses O(length + amount) space and O(length) time. See index::sample_weighted for details.

Example

use rand::prelude::*;

let choices = [('a', 2), ('b', 1), ('c', 1)];
let mut rng = rand::rng();
// First Draw * Second Draw = total odds
// -----------------------
// (50% * 50%) + (25% * 67%) = 41.7% chance that the output is `['a', 'b']` in some order.
// (50% * 50%) + (25% * 67%) = 41.7% chance that the output is `['a', 'c']` in some order.
// (25% * 33%) + (25% * 33%) = 16.6% chance that the output is `['b', 'c']` in some order.
println!("{:?}", choices.sample_weighted(&mut rng, 2, |item| item.1).unwrap().collect::<Vec<_>>());
fn choose_multiple<R>(&self, rng: &mut R, amount: usize) -> IndexedSamples<'_, Self, Self::Output>
where
    Self::Output: Sized,
    R: Rng + ?Sized,

Deprecated: use Self::sample instead

fn choose_multiple_array<R, const N: usize>(&self, rng: &mut R) -> Option<[Self::Output; N]>
where
    Self::Output: Clone + Sized,
    R: Rng + ?Sized,

Deprecated: use Self::sample_array instead

fn choose_multiple_weighted<R, F, X>(&self, rng: &mut R, amount: usize, weight: F) -> Result<IndexedSamples<'_, Self, Self::Output>, WeightError>
where
    Self::Output: Sized,
    R: Rng + ?Sized,
    F: Fn(&Self::Output) -> X,
    X: Into<f64>,

Deprecated: use Self::sample_weighted instead

Implementors