use std::collections::HashMap;
pub fn map<T, U>(arr: &[T], f: impl Fn(&T) -> U) -> Vec<U> {
arr.iter().map(f).collect()
}
pub fn filter<T: Clone>(arr: &[T], f: impl Fn(&T) -> bool) -> Vec<T> {
arr.iter().filter(|x| f(x)).cloned().collect()
}
pub fn filter_map<T, U>(arr: &[T], f: impl Fn(&T) -> Option<U>) -> Vec<U> {
arr.iter().filter_map(f).collect()
}
pub fn reduce<T, A>(arr: &[T], init: A, f: impl Fn(A, &T) -> A) -> A {
arr.iter().fold(init, f)
}
pub fn chunk<T: Clone>(arr: &[T], size: usize) -> Vec<Vec<T>> {
if size == 0 {
return vec![arr.to_vec()];
}
arr.chunks(size).map(|c| c.to_vec()).collect()
}
pub fn flatten<T: Clone>(arr: &[Vec<T>]) -> Vec<T> {
arr.iter().flatten().cloned().collect()
}
pub fn compact<T: Clone + Default + PartialEq>(arr: &[T]) -> Vec<T> {
arr.iter()
.filter(|x| **x != T::default())
.cloned()
.collect()
}
pub fn take<T: Clone>(arr: &[T], n: usize) -> Vec<T> {
arr.iter().take(n).cloned().collect()
}
pub fn skip<T: Clone>(arr: &[T], n: usize) -> Vec<T> {
arr.iter().skip(n).cloned().collect()
}
pub fn reverse<T: Clone>(arr: &[T]) -> Vec<T> {
let mut out: Vec<T> = arr.to_vec();
out.reverse();
out
}
pub fn zip<A: Clone, B: Clone>(a: &[A], b: &[B]) -> Vec<(A, B)> {
a.iter()
.zip(b.iter())
.map(|(x, y)| (x.clone(), y.clone()))
.collect()
}
pub fn first<T>(arr: &[T]) -> Option<&T> {
arr.first()
}
pub fn last<T>(arr: &[T]) -> Option<&T> {
arr.last()
}
pub fn get<T>(arr: &[T], index: usize) -> Option<&T> {
arr.get(index)
}
pub fn find<T>(arr: &[T], f: impl Fn(&T) -> bool) -> Option<&T> {
arr.iter().find(|x| f(x))
}
pub fn some<T>(arr: &[T], f: impl Fn(&T) -> bool) -> bool {
arr.iter().any(f)
}
pub fn every<T>(arr: &[T], f: impl Fn(&T) -> bool) -> bool {
arr.iter().all(f)
}
pub fn contains<T: PartialEq>(arr: &[T], value: &T) -> bool {
arr.iter().any(|x| x == value)
}
pub fn group_by<T, K>(arr: &[T], key_fn: impl Fn(&T) -> K) -> HashMap<K, Vec<T>>
where
K: Eq + std::hash::Hash,
T: Clone,
{
let mut map: HashMap<K, Vec<T>> = HashMap::new();
for item in arr {
map.entry(key_fn(item)).or_default().push(item.clone());
}
map
}
pub fn key_by<T, K>(arr: &[T], key_fn: impl Fn(&T) -> K) -> HashMap<K, T>
where
K: Eq + std::hash::Hash,
T: Clone,
{
let mut map: HashMap<K, T> = HashMap::new();
for item in arr {
map.insert(key_fn(item), item.clone());
}
map
}
pub fn pluck<T, U>(arr: &[T], extractor: impl Fn(&T) -> U) -> Vec<U> {
arr.iter().map(extractor).collect()
}
pub fn where_in<T: PartialEq + Clone>(arr: &[T], values: &[T]) -> Vec<T> {
arr.iter().filter(|x| values.contains(x)).cloned().collect()
}
pub fn count<T>(arr: &[T]) -> usize {
arr.len()
}
pub fn is_empty<T>(arr: &[T]) -> bool {
arr.is_empty()
}
pub fn is_not_empty<T>(arr: &[T]) -> bool {
!arr.is_empty()
}
pub fn unique<T: PartialEq + Clone>(arr: &[T]) -> Vec<T> {
let mut seen: Vec<T> = vec![];
arr.iter()
.filter(|x| {
if seen.contains(x) {
false
} else {
seen.push((*x).clone());
true
}
})
.cloned()
.collect()
}
pub fn without<T: PartialEq + Clone>(arr: &[T], values: &[T]) -> Vec<T> {
arr.iter()
.filter(|x| !values.contains(x))
.cloned()
.collect()
}
pub fn merge<T: Clone>(a: &[T], b: &[T]) -> Vec<T> {
let mut out = a.to_vec();
out.extend(b.iter().cloned());
out
}
pub fn intersect<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
a.iter().filter(|x| b.contains(x)).cloned().collect()
}
pub fn diff<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
a.iter().filter(|x| !b.contains(x)).cloned().collect()
}
pub fn sort_by<T: Clone>(arr: &[T], cmp: impl Fn(&T, &T) -> std::cmp::Ordering) -> Vec<T> {
let mut out = arr.to_vec();
out.sort_by(cmp);
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_map() {
let arr = [1, 2, 3];
let result = map(&arr, |x| x * 2);
assert_eq!(result, vec![2, 4, 6]);
}
#[test]
fn test_filter() {
let arr = [1, 2, 3, 4];
let result = filter(&arr, |x| *x % 2 == 0);
assert_eq!(result, vec![2, 4]);
}
#[test]
fn test_chunk() {
let arr = [1, 2, 3, 4, 5];
let result = chunk(&arr, 2);
assert_eq!(result, vec![vec![1, 2], vec![3, 4], vec![5]]);
}
#[test]
fn test_unique() {
let arr = [1, 2, 2, 3, 3, 3, 4];
let result = unique(&arr);
assert_eq!(result, vec![1, 2, 3, 4]);
}
#[test]
fn test_contains() {
let arr = [1, 2, 3];
assert!(contains(&arr, &2));
assert!(!contains(&arr, &5));
}
}