use std::collections::HashSet;
use rand::distributions::uniform::SampleRange;
use crate::random_number;
pub fn pick_random<'a, T>(
collection: &'a [T],
items_count: usize,
) -> Vec<&'a T> {
let iter = collection.iter();
let (_, len) = iter.size_hint();
let len = len.expect("Gennot get iterator length.");
assert!(
items_count <= len,
"Count must be smaller or equal to item length.",
);
let mut set = HashSet::new();
while set.len() < items_count {
set.insert(
random_number(0..len)
);
};
let result = iter
.enumerate()
.filter_map(|(index, item)| {
if set.contains(&index) {
return Some(item);
}
return None;
}).collect();
return result;
}
pub fn pick_random_rg<'a, T, R: SampleRange<usize>>(
collection: &'a [T],
range: R,
) -> Vec<&'a T> {
let items_count = random_number(range);
return pick_random(collection, items_count);
}
#[cfg(test)]
mod tests {
use crate::traits::Random;
use crate::random_number;
impl Random for u8 {
fn random() -> Self {
return random_number(0..=u8::MAX);
}
}
mod pick_random {
use random_vec::random_vec_rg;
use crate::{random_number, test::{random_vec, pick_random}};
#[test]
fn picks_random_items_from_vector() {
let test_vector: Vec<u8> = random_vec_rg(100..=200);
let original_test_vector_length = test_vector.len();
let items_count = random_number(30..=50);
let random_items = pick_random(&test_vector, items_count);
assert_eq!(
random_items.len(),
items_count,
"Must return vector with {} references.", items_count,
);
assert_eq!(
test_vector.len(),
original_test_vector_length,
"Test vector must not change.",
);
for item in random_items {
assert!(
test_vector.contains(item),
"Test vector must contain random item.",
);
}
}
#[test]
fn picks_random_items_from_slice() {
let test_vector: Vec<u8> = random_vec_rg(100..=200);
let original_test_vector_length = test_vector.len();
let items_count = random_number(3..=5);
let random_items = pick_random(&test_vector[..], items_count);
assert_eq!(
random_items.len(),
items_count,
"Must return vector with {} references.", items_count,
);
assert_eq!(
test_vector.len(),
original_test_vector_length,
"Test vector must not change.",
);
for item in random_items {
assert!(
test_vector.contains(item),
"Test vector must contain random item.",
);
}
}
}
mod pick_random_rg {
use random_vec::random_vec_rg;
use crate::{test::{random_vec, pick_random_rg}};
#[test]
fn picks_random_items_from_vector() {
let test_vector: Vec<u8> = random_vec_rg(100..=200);
let original_test_vector_length = test_vector.len();
let random_items = pick_random_rg(&test_vector, 30..=50);
assert!(
random_items.len() >= 30,
"Must return vector with at least 30 references.",
);
assert!(
random_items.len() <= 50,
"Must return vector with at most 50 references.",
);
assert_eq!(
test_vector.len(),
original_test_vector_length,
"Test vector must not change.",
);
for item in random_items {
assert!(
test_vector.contains(item),
"Test vector must contain random item.",
);
}
}
#[test]
fn picks_random_items_from_slice() {
let test_vector: Vec<u8> = random_vec_rg(100..=200);
let original_test_vector_length = test_vector.len();
let random_items = pick_random_rg(&test_vector[..], 30..=50);
assert!(
random_items.len() >= 30,
"Must return vector with at least 30 references.",
);
assert!(
random_items.len() <= 50,
"Must return vector with at most 50 references.",
);
assert_eq!(
test_vector.len(),
original_test_vector_length,
"Test vector must not change.",
);
for item in random_items {
assert!(
test_vector.contains(item),
"Test vector must contain random item.",
);
}
}
}
}