use crate::collection::Collection;
pub fn each<T, F>(collection: &[T], mut iteratee: F)
where
F: FnMut(&T),
{
for item in collection {
iteratee(item);
}
}
pub fn for_each<T, F>(collection: &[T], iteratee: F)
where
F: FnMut(&T),
{
each(collection, iteratee);
}
pub fn map<T, U, F>(collection: &[T], iteratee: F) -> Vec<U>
where
F: Fn(&T) -> U,
{
collection.iter().map(iteratee).collect()
}
pub fn filter<T, F>(collection: &[T], predicate: F) -> Vec<T>
where
T: Clone,
F: Fn(&T) -> bool,
{
collection.iter()
.filter(|item| predicate(item))
.cloned()
.collect()
}
pub fn reduce<T, U, F>(collection: &[T], iteratee: F, initial: U) -> U
where
F: Fn(U, &T) -> U,
{
collection.iter().fold(initial, iteratee)
}
pub fn reduce_right<T, U, F>(collection: &[T], iteratee: F, initial: U) -> U
where
F: Fn(U, &T) -> U,
{
collection.iter().rev().fold(initial, iteratee)
}
pub fn for_each_right<T, F>(collection: &[T], mut iteratee: F)
where
F: FnMut(&T),
{
for item in collection.iter().rev() {
iteratee(item);
}
}
impl<T> Collection<T> {
pub fn each<F>(&self, iteratee: F)
where
F: FnMut(&T),
{
each(&self.data, iteratee);
}
pub fn map<U, F>(&self, iteratee: F) -> Vec<U>
where
F: Fn(&T) -> U,
{
map(&self.data, iteratee)
}
pub fn filter<F>(&self, predicate: F) -> Vec<T>
where
T: Clone,
F: Fn(&T) -> bool,
{
filter(&self.data, predicate)
}
pub fn reduce<U, F>(&self, iteratee: F, initial: U) -> U
where
F: Fn(U, &T) -> U,
{
reduce(&self.data, iteratee, initial)
}
pub fn reduce_right<U, F>(&self, iteratee: F, initial: U) -> U
where
F: Fn(U, &T) -> U,
{
reduce_right(&self.data, iteratee, initial)
}
pub fn for_each_right<F>(&self, iteratee: F)
where
F: FnMut(&T),
{
for_each_right(&self.data, iteratee);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_each() {
let mut sum = 0;
each(&[1, 2, 3], |x| sum += x);
assert_eq!(sum, 6);
}
#[test]
fn test_for_each() {
let mut sum = 0;
for_each(&[1, 2, 3], |x| sum += x);
assert_eq!(sum, 6);
}
#[test]
fn test_map() {
let doubled = map(&[1, 2, 3], |x| x * 2);
assert_eq!(doubled, vec![2, 4, 6]);
let strings = map(&[1, 2, 3], std::string::ToString::to_string);
assert_eq!(strings, vec!["1", "2", "3"]);
}
#[test]
fn test_filter() {
let evens = filter(&[1, 2, 3, 4, 5], |x| x % 2 == 0);
assert_eq!(evens, vec![2, 4]);
}
#[test]
fn test_reduce() {
let sum = reduce(&[1, 2, 3, 4], |acc, x| acc + x, 0);
assert_eq!(sum, 10);
let result = reduce(&["a", "b", "c"], |acc, x| format!("{acc}{x}"), String::new());
assert_eq!(result, "abc");
}
#[test]
fn test_reduce_right() {
let result = reduce_right(&["a", "b", "c"], |acc, x| format!("{acc}{x}"), String::new());
assert_eq!(result, "cba");
}
#[test]
fn test_for_each_right() {
let mut result = Vec::new();
for_each_right(&[1, 2, 3], |x| result.push(*x));
assert_eq!(result, vec![3, 2, 1]);
}
#[test]
fn test_collection_each() {
let collection = Collection::new(vec![1, 2, 3]);
let mut sum = 0;
collection.each(|x| sum += x);
assert_eq!(sum, 6);
}
#[test]
fn test_collection_map() {
let collection = Collection::new(vec![1, 2, 3]);
let doubled = collection.map(|x| x * 2);
assert_eq!(doubled, vec![2, 4, 6]);
}
#[test]
fn test_collection_filter() {
let collection = Collection::new(vec![1, 2, 3, 4, 5]);
let evens = collection.filter(|x| x % 2 == 0);
assert_eq!(evens, vec![2, 4]);
}
#[test]
fn test_collection_reduce() {
let collection = Collection::new(vec![1, 2, 3, 4]);
let sum = collection.reduce(|acc, x| acc + x, 0);
assert_eq!(sum, 10);
}
#[test]
fn test_collection_reduce_right() {
let collection = Collection::new(vec!["a", "b", "c"]);
let result = collection.reduce_right(|acc, x| format!("{acc}{x}"), String::new());
assert_eq!(result, "cba");
}
#[test]
fn test_collection_for_each_right() {
let collection = Collection::new(vec![1, 2, 3]);
let mut result = Vec::new();
collection.for_each_right(|x| result.push(*x));
assert_eq!(result, vec![3, 2, 1]);
}
#[test]
fn test_empty_collection() {
let empty: Vec<i32> = vec![];
let result = map(&empty, |x| x * 2);
assert!(result.is_empty());
let sum = reduce(&empty, |acc, x| acc + x, 0);
assert_eq!(sum, 0);
}
}