1use std::collections::HashMap;
2
3pub fn map<T, U>(arr: &[T], f: impl Fn(&T) -> U) -> Vec<U> {
4 arr.iter().map(f).collect()
5}
6
7pub fn filter<T: Clone>(arr: &[T], f: impl Fn(&T) -> bool) -> Vec<T> {
8 arr.iter().filter(|x| f(x)).cloned().collect()
9}
10
11pub fn filter_map<T, U>(arr: &[T], f: impl Fn(&T) -> Option<U>) -> Vec<U> {
12 arr.iter().filter_map(f).collect()
13}
14
15pub fn reduce<T, A>(arr: &[T], init: A, f: impl Fn(A, &T) -> A) -> A {
16 arr.iter().fold(init, f)
17}
18
19pub fn chunk<T: Clone>(arr: &[T], size: usize) -> Vec<Vec<T>> {
20 if size == 0 {
21 return vec![arr.to_vec()];
22 }
23 arr.chunks(size).map(|c| c.to_vec()).collect()
24}
25
26pub fn flatten<T: Clone>(arr: &[Vec<T>]) -> Vec<T> {
27 arr.iter().flatten().cloned().collect()
28}
29
30pub fn compact<T: Clone + Default + PartialEq>(arr: &[T]) -> Vec<T> {
31 arr.iter()
32 .filter(|x| **x != T::default())
33 .cloned()
34 .collect()
35}
36
37pub fn take<T: Clone>(arr: &[T], n: usize) -> Vec<T> {
38 arr.iter().take(n).cloned().collect()
39}
40
41pub fn skip<T: Clone>(arr: &[T], n: usize) -> Vec<T> {
42 arr.iter().skip(n).cloned().collect()
43}
44
45pub fn reverse<T: Clone>(arr: &[T]) -> Vec<T> {
46 let mut out: Vec<T> = arr.to_vec();
47 out.reverse();
48 out
49}
50
51pub fn zip<A: Clone, B: Clone>(a: &[A], b: &[B]) -> Vec<(A, B)> {
52 a.iter()
53 .zip(b.iter())
54 .map(|(x, y)| (x.clone(), y.clone()))
55 .collect()
56}
57
58pub fn first<T>(arr: &[T]) -> Option<&T> {
59 arr.first()
60}
61
62pub fn last<T>(arr: &[T]) -> Option<&T> {
63 arr.last()
64}
65
66pub fn get<T>(arr: &[T], index: usize) -> Option<&T> {
67 arr.get(index)
68}
69
70pub fn find<T>(arr: &[T], f: impl Fn(&T) -> bool) -> Option<&T> {
71 arr.iter().find(|x| f(x))
72}
73
74pub fn some<T>(arr: &[T], f: impl Fn(&T) -> bool) -> bool {
75 arr.iter().any(f)
76}
77
78pub fn every<T>(arr: &[T], f: impl Fn(&T) -> bool) -> bool {
79 arr.iter().all(f)
80}
81
82pub fn contains<T: PartialEq>(arr: &[T], value: &T) -> bool {
83 arr.iter().any(|x| x == value)
84}
85
86pub fn group_by<T, K>(arr: &[T], key_fn: impl Fn(&T) -> K) -> HashMap<K, Vec<T>>
87where
88 K: Eq + std::hash::Hash,
89 T: Clone,
90{
91 let mut map: HashMap<K, Vec<T>> = HashMap::new();
92 for item in arr {
93 map.entry(key_fn(item)).or_default().push(item.clone());
94 }
95 map
96}
97
98pub fn key_by<T, K>(arr: &[T], key_fn: impl Fn(&T) -> K) -> HashMap<K, T>
99where
100 K: Eq + std::hash::Hash,
101 T: Clone,
102{
103 let mut map: HashMap<K, T> = HashMap::new();
104 for item in arr {
105 map.insert(key_fn(item), item.clone());
106 }
107 map
108}
109
110pub fn pluck<T, U>(arr: &[T], extractor: impl Fn(&T) -> U) -> Vec<U> {
111 arr.iter().map(extractor).collect()
112}
113
114pub fn where_in<T: PartialEq + Clone>(arr: &[T], values: &[T]) -> Vec<T> {
115 arr.iter().filter(|x| values.contains(x)).cloned().collect()
116}
117
118pub fn count<T>(arr: &[T]) -> usize {
119 arr.len()
120}
121
122pub fn is_empty<T>(arr: &[T]) -> bool {
123 arr.is_empty()
124}
125
126pub fn is_not_empty<T>(arr: &[T]) -> bool {
127 !arr.is_empty()
128}
129
130pub fn unique<T: PartialEq + Clone>(arr: &[T]) -> Vec<T> {
131 let mut seen: Vec<T> = vec![];
132 arr.iter()
133 .filter(|x| {
134 if seen.contains(x) {
135 false
136 } else {
137 seen.push((*x).clone());
138 true
139 }
140 })
141 .cloned()
142 .collect()
143}
144
145pub fn without<T: PartialEq + Clone>(arr: &[T], values: &[T]) -> Vec<T> {
146 arr.iter()
147 .filter(|x| !values.contains(x))
148 .cloned()
149 .collect()
150}
151
152pub fn merge<T: Clone>(a: &[T], b: &[T]) -> Vec<T> {
153 let mut out = a.to_vec();
154 out.extend(b.iter().cloned());
155 out
156}
157
158pub fn intersect<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
159 a.iter().filter(|x| b.contains(x)).cloned().collect()
160}
161
162pub fn diff<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
163 a.iter().filter(|x| !b.contains(x)).cloned().collect()
164}
165
166pub fn sort_by<T: Clone>(arr: &[T], cmp: impl Fn(&T, &T) -> std::cmp::Ordering) -> Vec<T> {
167 let mut out = arr.to_vec();
168 out.sort_by(cmp);
169 out
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn test_map() {
178 let arr = [1, 2, 3];
179 let result = map(&arr, |x| x * 2);
180 assert_eq!(result, vec![2, 4, 6]);
181 }
182
183 #[test]
184 fn test_filter() {
185 let arr = [1, 2, 3, 4];
186 let result = filter(&arr, |x| *x % 2 == 0);
187 assert_eq!(result, vec![2, 4]);
188 }
189
190 #[test]
191 fn test_chunk() {
192 let arr = [1, 2, 3, 4, 5];
193 let result = chunk(&arr, 2);
194 assert_eq!(result, vec![vec![1, 2], vec![3, 4], vec![5]]);
195 }
196
197 #[test]
198 fn test_unique() {
199 let arr = [1, 2, 2, 3, 3, 3, 4];
200 let result = unique(&arr);
201 assert_eq!(result, vec![1, 2, 3, 4]);
202 }
203
204 #[test]
205 fn test_contains() {
206 let arr = [1, 2, 3];
207 assert!(contains(&arr, &2));
208 assert!(!contains(&arr, &5));
209 }
210}