rust_prelude_plus/
collections.rs

1//! Collection operations for keypath-based functional programming
2
3use key_paths_core::KeyPaths;
4use crate::error::{KeyPathResult, KeyPathError};
5use crate::traits::KeyPathsOperable;
6use std::collections::{HashMap, HashSet, BTreeMap};
7
8/// Extension trait for collections with keypath operations
9pub trait KeyPathsCollectionExt<T> {
10    /// Extract values from keypaths into collections
11    fn collect_keypath<V>(&self, keypath: KeyPaths<T, V>) -> KeyPathResult<Vec<V>>
12    where
13        V: Clone;
14    
15    /// Partition elements by keypath predicate
16    fn partition_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<(Vec<T>, Vec<T>)>
17    where
18        T: Clone,
19        F: Fn(&V) -> bool;
20    
21    /// Group elements by keypath values
22    fn group_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, f: F) -> KeyPathResult<HashMap<V, Vec<T>>>
23    where
24        V: std::hash::Hash + Eq + Clone,
25        T: Clone,
26        F: Fn(&V) -> V;
27    
28    /// Sort elements by keypath values
29    fn sort_by_keypath<V, F>(&mut self, keypath: KeyPaths<T, V>, compare: F) -> KeyPathResult<()>
30    where
31        F: Fn(&V, &V) -> std::cmp::Ordering;
32    
33    /// Find elements matching keypath conditions
34    fn find_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<Option<&T>>
35    where
36        F: Fn(&V) -> bool;
37    
38    /// Check if any element matches keypath condition
39    fn any_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<bool>
40    where
41        F: Fn(&V) -> bool;
42    
43    /// Check if all elements match keypath condition
44    fn all_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<bool>
45    where
46        F: Fn(&V) -> bool;
47    
48    /// Count elements matching keypath condition
49    fn count_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<usize>
50    where
51        F: Fn(&V) -> bool;
52    
53    /// Get unique values from keypath
54    fn unique_by_keypath<V>(&self, keypath: KeyPaths<T, V>) -> KeyPathResult<HashSet<V>>
55    where
56        V: std::hash::Hash + Eq + Clone;
57    
58    /// Get distinct values from keypath with counts
59    fn distinct_by_keypath<V>(&self, keypath: KeyPaths<T, V>) -> KeyPathResult<HashMap<V, usize>>
60    where
61        V: std::hash::Hash + Eq + Clone;
62    
63    /// Zip with another collection using keypath values
64    fn zip_with_keypath<U, V1, V2, F, R>(
65        &self,
66        other: &[U],
67        keypath1: KeyPaths<T, V1>,
68        keypath2: KeyPaths<U, V2>,
69        f: F,
70    ) -> KeyPathResult<Vec<R>>
71    where
72        F: Fn(&V1, &V2) -> R;
73    
74    /// Window operations over keypath values
75    fn window_by_keypath<V, F, R>(
76        &self,
77        keypath: KeyPaths<T, V>,
78        window_size: usize,
79        f: F,
80    ) -> KeyPathResult<Vec<R>>
81    where
82        V: Clone,
83        F: Fn(&[V]) -> R;
84    
85    /// Rolling operations over keypath values
86    fn rolling_by_keypath<V, F, R>(
87        &self,
88        keypath: KeyPaths<T, V>,
89        window_size: usize,
90        f: F,
91    ) -> KeyPathResult<Vec<R>>
92    where
93        V: Clone,
94        F: Fn(&[V]) -> R;
95}
96
97impl<T: KeyPathsOperable> KeyPathsCollectionExt<T> for Vec<T> {
98    fn collect_keypath<V>(&self, keypath: KeyPaths<T, V>) -> KeyPathResult<Vec<V>>
99    where
100        V: Clone,
101    {
102        let mut result = Vec::with_capacity(self.len());
103            for item in self {
104                let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
105                    panic!("KeyPath access failed in collect_keypath")
106                });
107                result.push(value.clone());
108            }
109        Ok(result)
110    }
111    
112    fn partition_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<(Vec<T>, Vec<T>)>
113    where
114        T: Clone,
115        F: Fn(&V) -> bool,
116    {
117        let mut left = Vec::new();
118        let mut right = Vec::new();
119        
120            for item in self {
121                let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
122                    panic!("KeyPath access failed in partition_by_keypath")
123                });
124                if predicate(value) {
125                    left.push(item.clone());
126                } else {
127                    right.push(item.clone());
128                }
129            }
130        
131        Ok((left, right))
132    }
133    
134    fn group_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, f: F) -> KeyPathResult<HashMap<V, Vec<T>>>
135    where
136        V: std::hash::Hash + Eq + Clone,
137        T: Clone,
138        F: Fn(&V) -> V,
139    {
140        let mut groups = HashMap::new();
141        for item in self {
142            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
143                panic!("KeyPath access failed in group_by_keypath")
144            });
145            let key = f(value);
146            groups.entry(key).or_insert_with(Vec::new).push(item.clone());
147        }
148        Ok(groups)
149    }
150    
151    fn sort_by_keypath<V, F>(&mut self, keypath: KeyPaths<T, V>, compare: F) -> KeyPathResult<()>
152    where
153        F: Fn(&V, &V) -> std::cmp::Ordering,
154    {
155        self.sort_by(|a, b| {
156            let a_val = a.get_at_keypath(&keypath).unwrap_or_else(|_| {
157                panic!("KeyPath access failed in sort_by_keypath")
158            });
159            let b_val = b.get_at_keypath(&keypath).unwrap_or_else(|_| {
160                panic!("KeyPath access failed in sort_by_keypath")
161            });
162            compare(a_val, b_val)
163        });
164        Ok(())
165    }
166    
167    fn find_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<Option<&T>>
168    where
169        F: Fn(&V) -> bool,
170    {
171        for item in self {
172            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
173                panic!("KeyPath access failed in find_by_keypath")
174            });
175            if predicate(value) {
176                return Ok(Some(item));
177            }
178        }
179        Ok(None)
180    }
181    
182    fn any_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<bool>
183    where
184        F: Fn(&V) -> bool,
185    {
186        for item in self {
187            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
188                panic!("KeyPath access failed in any_by_keypath")
189            });
190            if predicate(value) {
191                return Ok(true);
192            }
193        }
194        Ok(false)
195    }
196    
197    fn all_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<bool>
198    where
199        F: Fn(&V) -> bool,
200    {
201        for item in self {
202            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
203                panic!("KeyPath access failed in all_by_keypath")
204            });
205            if !predicate(value) {
206                return Ok(false);
207            }
208        }
209        Ok(true)
210    }
211    
212    fn count_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<usize>
213    where
214        F: Fn(&V) -> bool,
215    {
216        let mut count = 0;
217        for item in self {
218            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
219                panic!("KeyPath access failed in count_by_keypath")
220            });
221            if predicate(value) {
222                count += 1;
223            }
224        }
225        Ok(count)
226    }
227    
228    fn unique_by_keypath<V>(&self, keypath: KeyPaths<T, V>) -> KeyPathResult<HashSet<V>>
229    where
230        V: std::hash::Hash + Eq + Clone,
231    {
232        let mut unique = HashSet::new();
233        for item in self {
234            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
235                panic!("KeyPath access failed in unique_by_keypath")
236            });
237            unique.insert(value.clone());
238        }
239        Ok(unique)
240    }
241    
242    fn distinct_by_keypath<V>(&self, keypath: KeyPaths<T, V>) -> KeyPathResult<HashMap<V, usize>>
243    where
244        V: std::hash::Hash + Eq + Clone,
245    {
246        let mut counts = HashMap::new();
247        for item in self {
248            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
249                panic!("KeyPath access failed in distinct_by_keypath")
250            });
251            *counts.entry(value.clone()).or_insert(0) += 1;
252        }
253        Ok(counts)
254    }
255    
256    fn zip_with_keypath<U, V1, V2, F, R>(
257        &self,
258        other: &[U],
259        keypath1: KeyPaths<T, V1>,
260        keypath2: KeyPaths<U, V2>,
261        f: F,
262    ) -> KeyPathResult<Vec<R>>
263    where
264        U: KeyPathsOperable,
265        F: Fn(&V1, &V2) -> R,
266    {
267        let min_len = self.len().min(other.len());
268        let mut result = Vec::with_capacity(min_len);
269        
270        for i in 0..min_len {
271            let value1 = self[i].get_at_keypath(&keypath1).unwrap_or_else(|_| {
272                panic!("KeyPath access failed in zip_with_keypath")
273            });
274            let value2 = other[i].get_at_keypath(&keypath2).unwrap_or_else(|_| {
275                panic!("KeyPath access failed in zip_with_keypath")
276            });
277            result.push(f(value1, value2));
278        }
279        
280        Ok(result)
281    }
282    
283    fn window_by_keypath<V, F, R>(
284        &self,
285        keypath: KeyPaths<T, V>,
286        window_size: usize,
287        f: F,
288    ) -> KeyPathResult<Vec<R>>
289    where
290        V: Clone,
291        F: Fn(&[V]) -> R,
292    {
293        if window_size == 0 || window_size > self.len() {
294            return Err(KeyPathError::CollectionError {
295                message: format!("Invalid window size: {}", window_size),
296            });
297        }
298        
299        let mut result = Vec::new();
300        for i in 0..=self.len() - window_size {
301            let window: Vec<V> = self[i..i + window_size]
302                .iter()
303                .map(|item| item.get_at_keypath(&keypath).unwrap_or_else(|_| {
304                    panic!("KeyPath access failed in window_by_keypath")
305                }).clone())
306                .collect();
307            result.push(f(&window));
308        }
309        
310        Ok(result)
311    }
312    
313    fn rolling_by_keypath<V, F, R>(
314        &self,
315        keypath: KeyPaths<T, V>,
316        window_size: usize,
317        f: F,
318    ) -> KeyPathResult<Vec<R>>
319    where
320        V: Clone,
321        F: Fn(&[V]) -> R,
322    {
323        if window_size == 0 {
324            return Err(KeyPathError::CollectionError {
325                message: "Window size must be greater than 0".to_string(),
326            });
327        }
328        
329        let mut result = Vec::new();
330        let mut window = Vec::with_capacity(window_size);
331        
332        for item in self {
333            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
334                panic!("KeyPath access failed in rolling_by_keypath")
335            }).clone();
336            window.push(value);
337            
338            if window.len() == window_size {
339                result.push(f(&window));
340                window.remove(0);
341            }
342        }
343        
344        Ok(result)
345    }
346}
347
348/// Specialized collection operations for different data structures
349pub mod specialized {
350    use super::*;
351    
352    /// Operations for HashMap collections
353    pub trait KeyPathsHashMapExt<K, V> {
354        /// Transform values using keypath
355        fn map_values_keypath<T, F, R>(&self, keypath: KeyPaths<V, T>, f: F) -> KeyPathResult<HashMap<K, R>>
356        where
357            K: Clone,
358            F: Fn(&T) -> R;
359        
360        /// Filter by keypath predicate on values
361        fn filter_values_keypath<T, F>(&self, keypath: KeyPaths<V, T>, predicate: F) -> KeyPathResult<HashMap<K, V>>
362        where
363            K: Clone,
364            V: Clone,
365            F: Fn(&T) -> bool;
366    }
367    
368    impl<K: std::hash::Hash + std::cmp::Eq, V: KeyPathsOperable> KeyPathsHashMapExt<K, V> for HashMap<K, V> {
369        fn map_values_keypath<T, F, R>(&self, keypath: KeyPaths<V, T>, f: F) -> KeyPathResult<HashMap<K, R>>
370        where
371            K: Clone,
372            F: Fn(&T) -> R,
373        {
374            let mut result = HashMap::new();
375            for (key, value) in self {
376                let keypath_value = value.get_at_keypath(&keypath).unwrap_or_else(|_| {
377                    panic!("KeyPath access failed in map_values_keypath")
378                });
379                result.insert(key.clone(), f(keypath_value));
380            }
381            Ok(result)
382        }
383        
384        fn filter_values_keypath<T, F>(&self, keypath: KeyPaths<V, T>, predicate: F) -> KeyPathResult<HashMap<K, V>>
385        where
386            K: Clone,
387            V: Clone,
388            F: Fn(&T) -> bool,
389        {
390            let mut result = HashMap::new();
391            for (key, value) in self {
392                let keypath_value = keypath.get(value).unwrap_or_else(|| {
393                    panic!("KeyPath access failed in filter_values_keypath")
394                });
395                if predicate(keypath_value) {
396                    result.insert(key.clone(), value.clone());
397                }
398            }
399            Ok(result)
400        }
401    }
402    
403    /// Operations for BTreeMap collections
404    pub trait KeyPathsBTreeMapExt<K, V> {
405        /// Transform values using keypath
406        fn map_values_keypath<T, F, R>(&self, keypath: KeyPaths<V, T>, f: F) -> KeyPathResult<BTreeMap<K, R>>
407        where
408            K: Clone + Ord,
409            F: Fn(&T) -> R;
410        
411        /// Filter by keypath predicate on values
412        fn filter_values_keypath<T, F>(&self, keypath: KeyPaths<V, T>, predicate: F) -> KeyPathResult<BTreeMap<K, V>>
413        where
414            K: Clone + Ord,
415            V: Clone,
416            F: Fn(&T) -> bool;
417    }
418    
419    impl<K: std::cmp::Ord, V: KeyPathsOperable> KeyPathsBTreeMapExt<K, V> for BTreeMap<K, V> {
420        fn map_values_keypath<T, F, R>(&self, keypath: KeyPaths<V, T>, f: F) -> KeyPathResult<BTreeMap<K, R>>
421        where
422            K: Clone + Ord,
423            F: Fn(&T) -> R,
424        {
425            let mut result = BTreeMap::new();
426            for (key, value) in self {
427                let keypath_value = value.get_at_keypath(&keypath).unwrap_or_else(|_| {
428                    panic!("KeyPath access failed in map_values_keypath")
429                });
430                result.insert(key.clone(), f(keypath_value));
431            }
432            Ok(result)
433        }
434        
435        fn filter_values_keypath<T, F>(&self, keypath: KeyPaths<V, T>, predicate: F) -> KeyPathResult<BTreeMap<K, V>>
436        where
437            K: Clone + Ord,
438            V: Clone,
439            F: Fn(&T) -> bool,
440        {
441            let mut result = BTreeMap::new();
442            for (key, value) in self {
443                let keypath_value = keypath.get(value).unwrap_or_else(|| {
444                    panic!("KeyPath access failed in filter_values_keypath")
445                });
446                if predicate(keypath_value) {
447                    result.insert(key.clone(), value.clone());
448                }
449            }
450            Ok(result)
451        }
452    }
453}
454
455/// Utility functions for collection operations
456pub mod utils {
457    use super::*;
458    
459    /// Create a keypath-based comparator for sorting
460    pub fn create_keypath_comparator<T: KeyPathsOperable, V, F>(
461        keypath: KeyPaths<T, V>,
462        compare: F,
463    ) -> impl Fn(&T, &T) -> std::cmp::Ordering
464    where
465        F: Fn(&V, &V) -> std::cmp::Ordering,
466    {
467        move |a, b| {
468            let a_val = a.get_at_keypath(&keypath).unwrap_or_else(|_| {
469                panic!("KeyPath access failed in create_keypath_comparator")
470            });
471            let b_val = b.get_at_keypath(&keypath).unwrap_or_else(|_| {
472                panic!("KeyPath access failed in create_keypath_comparator")
473            });
474            compare(a_val, b_val)
475        }
476    }
477    
478    /// Create a keypath-based hash function
479    pub fn create_keypath_hasher<T: KeyPathsOperable, V, H>(
480        keypath: KeyPaths<T, V>,
481        hasher: H,
482    ) -> impl Fn(&T) -> u64
483    where
484        H: Fn(&V) -> u64,
485    {
486        move |item| {
487            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
488                panic!("KeyPath access failed in create_keypath_hasher")
489            });
490            hasher(value)
491        }
492    }
493    
494    /// Create a keypath-based equality function
495    pub fn create_keypath_equality<T: KeyPathsOperable, V, E>(
496        keypath: KeyPaths<T, V>,
497        equality: E,
498    ) -> impl Fn(&T, &T) -> bool
499    where
500        E: Fn(&V, &V) -> bool,
501    {
502        move |a, b| {
503            let a_val = a.get_at_keypath(&keypath).unwrap_or_else(|_| {
504                panic!("KeyPath access failed in create_keypath_equality")
505            });
506            let b_val = b.get_at_keypath(&keypath).unwrap_or_else(|_| {
507                panic!("KeyPath access failed in create_keypath_equality")
508            });
509            equality(a_val, b_val)
510        }
511    }
512}