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