pub trait IndexedRandom: Index<usize> {
// Required method
fn len(&self) -> usize;
// Provided methods
fn is_empty(&self) -> bool { ... }
fn choose<R>(&self, rng: &mut R) -> Option<&Self::Output>
where R: Rng + ?Sized { ... }
fn choose_multiple<R>(
&self,
rng: &mut R,
amount: usize,
) -> SliceChooseIter<'_, Self, Self::Output> ⓘ
where Self::Output: Sized,
R: Rng + ?Sized { ... }
fn choose_multiple_array<R, const N: usize>(
&self,
rng: &mut R,
) -> Option<[Self::Output; N]>
where Self::Output: Clone + Sized,
R: Rng + ?Sized { ... }
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> { ... }
fn choose_multiple_weighted<R, F, X>(
&self,
rng: &mut R,
amount: usize,
weight: F,
) -> Result<SliceChooseIter<'_, Self, Self::Output>, WeightError>
where Self::Output: Sized,
R: Rng + ?Sized,
F: Fn(&Self::Output) -> X,
X: Into<f64> { ... }
}
Expand description
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§
Provided Methods§
sourcefn choose<R>(&self, rng: &mut R) -> Option<&Self::Output>
fn choose<R>(&self, rng: &mut R) -> Option<&Self::Output>
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);
sourcefn choose_multiple<R>(
&self,
rng: &mut R,
amount: usize,
) -> SliceChooseIter<'_, Self, Self::Output> ⓘ
fn choose_multiple<R>( &self, rng: &mut R, amount: usize, ) -> SliceChooseIter<'_, Self, Self::Output> ⓘ
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.choose_multiple(&mut rng, 3).cloned().collect();
// store in a buffer:
let mut buf = [0u8; 5];
for (b, slot) in sample.choose_multiple(&mut rng, buf.len()).zip(buf.iter_mut()) {
*slot = *b;
}
sourcefn choose_multiple_array<R, const N: usize>(
&self,
rng: &mut R,
) -> Option<[Self::Output; N]>
fn choose_multiple_array<R, const N: usize>( &self, rng: &mut R, ) -> Option<[Self::Output; N]>
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.choose_multiple_array(&mut rng).unwrap();
sourcefn 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>,
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. Returns None
only if the slice is empty.
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 distr::WeightedIndex
.
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);
sourcefn choose_multiple_weighted<R, F, X>(
&self,
rng: &mut R,
amount: usize,
weight: F,
) -> Result<SliceChooseIter<'_, Self, Self::Output>, WeightError>
fn choose_multiple_weighted<R, F, X>( &self, rng: &mut R, amount: usize, weight: F, ) -> Result<SliceChooseIter<'_, Self, Self::Output>, WeightError>
Biased sampling of amount
distinct elements
Similar to choose_multiple
, but where the likelihood of each element’s
inclusion in the output may be specified. 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)
.
If all of the weights are equal, even if they are all zero, each element has an equal likelihood of being selected.
This implementation uses O(length + amount)
space and O(length)
time
if the “nightly” feature is enabled, or O(length)
space and
O(length + amount * log length)
time otherwise.
§Known issues
The algorithm currently used to implement this method loses accuracy when small values are used for weights. See #1476.
§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.choose_multiple_weighted(&mut rng, 2, |item| item.1).unwrap().collect::<Vec<_>>());