Skip to main content

rok_utils/
arr.rs

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}