use rand::Rng;
pub fn reservoir_sample<I, T, R>(iter: I, n: usize, rng: &mut R) -> Vec<T>
where
I: IntoIterator<Item = T>,
R: Rng + ?Sized,
{
let mut reservoir = Vec::with_capacity(n);
let mut iter = iter.into_iter().enumerate();
while reservoir.len() < n
&& let Some((_, item)) = iter.next()
{
reservoir.push(item);
}
for (i, item) in iter {
let j = rng.random_range(0..=i);
if j < n {
reservoir[j] = item;
}
}
reservoir
}
pub trait ReservoirSampleExt: Iterator {
fn reservoir_sample_with<R: Rng + ?Sized>(self, n: usize, rng: &mut R) -> Vec<Self::Item>
where
Self: Sized,
{
reservoir_sample(self, n, rng)
}
fn reservoir_sample(self, n: usize) -> Vec<Self::Item>
where
Self: Sized,
{
self.reservoir_sample_with(n, &mut rand::rng())
}
}
impl<I: Iterator> ReservoirSampleExt for I {}