Skip to main content

rinq/core/builder/
sorted.rs

1// src/core/builder/sorted.rs
2// impl QueryBuilder<T, Sorted>
3
4use super::iterators::{ChunkIterator, WindowIterator};
5use super::{QueryBuilder, QueryData};
6use crate::core::state::{Filtered, Sorted};
7use crate::core::state_diagnostics::HashEqBound;
8use num_traits::ToPrimitive;
9use std::cmp::Ordering;
10use std::collections::{HashMap, HashSet, VecDeque};
11use std::hash::Hash;
12use std::iter::Sum;
13use std::marker::PhantomData;
14
15impl<T: 'static> QueryBuilder<T, Sorted> {
16    /// Inspect elements without consuming the query
17    ///
18    /// **実行種別**: 遅延ストリーミング
19    ///
20    /// Note: This converts Sorted state to Filtered state for lazy evaluation
21    #[inline]
22    pub fn inspect<F>(self, f: F) -> QueryBuilder<T, Filtered>
23    where
24        F: Fn(&T) + 'static,
25    {
26        match self.data {
27            QueryData::SortedVec { items, .. } => {
28                // Convert to iterator and apply inspect for lazy evaluation
29                QueryBuilder {
30                    data: QueryData::Iterator(Box::new(items.into_iter().inspect(f))),
31                    _state: PhantomData,
32                }
33            }
34            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
35        }
36    }
37
38    /// Apply a secondary sort key (stable sort preserving primary order)
39    ///
40    /// **実行種別**: 遅延非ストリーミング(再ソートのため全要素を収集)
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use rinq::QueryBuilder;
46    ///
47    /// #[derive(Debug, Clone, PartialEq)]
48    /// struct Person { name: String, age: i32 }
49    ///
50    /// let data = vec![
51    ///     Person { name: "Alice".to_string(), age: 30 },
52    ///     Person { name: "Bob".to_string(), age: 25 },
53    ///     Person { name: "Charlie".to_string(), age: 30 },
54    /// ];
55    ///
56    /// let result: Vec<_> = QueryBuilder::from(data)
57    ///     .where_(|_| true)
58    ///     .order_by(|p| p.age)
59    ///     .then_by(|p| p.name.clone())
60    ///     .collect();
61    /// // Sorted first by age, then by name within same age
62    /// ```
63    #[inline]
64    pub fn then_by<K, F>(self, key_selector: F) -> QueryBuilder<T, Sorted>
65    where
66        F: Fn(&T) -> K + 'static,
67        K: Ord + 'static,
68        T: 'static,
69    {
70        match self.data {
71            QueryData::SortedVec {
72                mut items,
73                comparator,
74            } => {
75                let primary_comparator = comparator;
76                let new_comparator = Box::new(move |a: &T, b: &T| match primary_comparator(a, b) {
77                    Ordering::Equal => key_selector(a).cmp(&key_selector(b)),
78                    other => other,
79                });
80
81                items.sort_by(|a, b| new_comparator(a, b));
82
83                QueryBuilder {
84                    data: QueryData::SortedVec {
85                        items,
86                        comparator: new_comparator,
87                    },
88                    _state: PhantomData,
89                }
90            }
91            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
92        }
93    }
94
95    /// Apply a secondary sort key in descending order (stable sort preserving primary order)
96    ///
97    /// **実行種別**: 遅延非ストリーミング(再ソートのため全要素を収集)
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use rinq::QueryBuilder;
103    ///
104    /// #[derive(Debug, Clone, PartialEq)]
105    /// struct Item { category: &'static str, priority: i32 }
106    ///
107    /// let data = vec![
108    ///     Item { category: "A", priority: 2 },
109    ///     Item { category: "B", priority: 5 },
110    ///     Item { category: "A", priority: 7 },
111    ///     Item { category: "B", priority: 1 },
112    /// ];
113    ///
114    /// // Sort by category ascending, then by priority descending within same category
115    /// let result: Vec<_> = QueryBuilder::from(data)
116    ///     .where_(|_| true)
117    ///     .order_by(|item| item.category)
118    ///     .then_by_descending(|item| item.priority)
119    ///     .collect();
120    ///
121    /// assert_eq!(result[0].category, "A");
122    /// assert_eq!(result[0].priority, 7); // higher priority first within "A"
123    /// assert_eq!(result[2].category, "B");
124    /// assert_eq!(result[2].priority, 5); // higher priority first within "B"
125    /// ```
126    #[inline]
127    pub fn then_by_descending<K, F>(self, key_selector: F) -> QueryBuilder<T, Sorted>
128    where
129        F: Fn(&T) -> K + 'static,
130        K: Ord + 'static,
131        T: 'static,
132    {
133        match self.data {
134            QueryData::SortedVec {
135                mut items,
136                comparator,
137            } => {
138                let primary_comparator = comparator;
139                let new_comparator = Box::new(move |a: &T, b: &T| match primary_comparator(a, b) {
140                    Ordering::Equal => key_selector(b).cmp(&key_selector(a)),
141                    other => other,
142                });
143
144                items.sort_by(|a, b| new_comparator(a, b));
145
146                QueryBuilder {
147                    data: QueryData::SortedVec {
148                        items,
149                        comparator: new_comparator,
150                    },
151                    _state: PhantomData,
152                }
153            }
154            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
155        }
156    }
157
158    /// Take at most n elements from sorted query
159    #[inline]
160    pub fn take(self, n: usize) -> QueryBuilder<T, Filtered> {
161        match self.data {
162            QueryData::SortedVec { items, .. } => QueryBuilder {
163                data: QueryData::Iterator(Box::new(items.into_iter().take(n))),
164                _state: PhantomData,
165            },
166            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
167        }
168    }
169
170    /// Skip the first n elements from sorted query
171    #[inline]
172    pub fn skip(self, n: usize) -> QueryBuilder<T, Filtered> {
173        match self.data {
174            QueryData::SortedVec { items, .. } => QueryBuilder {
175                data: QueryData::Iterator(Box::new(items.into_iter().skip(n))),
176                _state: PhantomData,
177            },
178            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
179        }
180    }
181
182    /// Take elements while the predicate holds
183    ///
184    /// **実行種別**: 遅延ストリーミング
185    #[inline]
186    pub fn take_while<F>(self, predicate: F) -> QueryBuilder<T, Filtered>
187    where
188        F: Fn(&T) -> bool + 'static,
189    {
190        match self.data {
191            QueryData::SortedVec { items, .. } => QueryBuilder {
192                data: QueryData::Iterator(Box::new(
193                    items.into_iter().take_while(move |x| predicate(x)),
194                )),
195                _state: PhantomData,
196            },
197            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
198        }
199    }
200
201    /// Skip elements while the predicate holds
202    ///
203    /// **実行種別**: 遅延ストリーミング
204    #[inline]
205    pub fn skip_while<F>(self, predicate: F) -> QueryBuilder<T, Filtered>
206    where
207        F: Fn(&T) -> bool + 'static,
208    {
209        match self.data {
210            QueryData::SortedVec { items, .. } => QueryBuilder {
211                data: QueryData::Iterator(Box::new(
212                    items.into_iter().skip_while(move |x| predicate(x)),
213                )),
214                _state: PhantomData,
215            },
216            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
217        }
218    }
219
220    /// Calculate the sum of all sorted elements
221    #[inline]
222    pub fn sum(self) -> T
223    where
224        T: Sum,
225    {
226        match self.data {
227            QueryData::SortedVec { items, .. } => items.into_iter().sum(),
228            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
229        }
230    }
231
232    /// Calculate the average of all sorted elements
233    #[inline]
234    pub fn average(self) -> Option<f64>
235    where
236        T: ToPrimitive,
237    {
238        match self.data {
239            QueryData::SortedVec { items, .. } => {
240                if items.is_empty() {
241                    return None;
242                }
243                let sum: f64 = items.iter().filter_map(|x| x.to_f64()).sum();
244                Some(sum / items.len() as f64)
245            }
246            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
247        }
248    }
249
250    /// Find the minimum element (O(1) for sorted data)
251    ///
252    /// Optimized: Returns the first element from sorted collection in O(1) time.
253    #[inline]
254    pub fn min(self) -> Option<T>
255    where
256        T: Ord,
257    {
258        match self.data {
259            QueryData::SortedVec { mut items, .. } => {
260                // Optimization: First element is minimum in sorted collection
261                if items.is_empty() {
262                    None
263                } else {
264                    Some(items.remove(0))
265                }
266            }
267            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
268        }
269    }
270
271    /// Find the maximum element (O(1) for sorted data)
272    ///
273    /// Optimized: Returns the last element from sorted collection in O(1) time.
274    #[inline]
275    pub fn max(self) -> Option<T>
276    where
277        T: Ord,
278    {
279        match self.data {
280            QueryData::SortedVec { mut items, .. } => {
281                // Optimization: Last element is maximum in sorted collection
282                items.pop()
283            }
284            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
285        }
286    }
287
288    /// Find the element with the minimum key value
289    #[inline]
290    pub fn min_by<K, F>(self, key_selector: F) -> Option<T>
291    where
292        F: Fn(&T) -> K,
293        K: Ord,
294    {
295        match self.data {
296            QueryData::SortedVec { items, .. } => items.into_iter().min_by_key(key_selector),
297            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
298        }
299    }
300
301    /// Find the element with the maximum key value
302    #[inline]
303    pub fn max_by<K, F>(self, key_selector: F) -> Option<T>
304    where
305        F: Fn(&T) -> K,
306        K: Ord,
307    {
308        match self.data {
309            QueryData::SortedVec { items, .. } => items.into_iter().max_by_key(key_selector),
310            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
311        }
312    }
313
314    /// Group sorted elements by a key function
315    ///
316    /// **実行種別**: 即時実行
317    #[inline]
318    pub fn group_by<K, F>(self, key_selector: F) -> HashMap<K, Vec<T>>
319    where
320        F: Fn(&T) -> K,
321        K: Eq + Hash,
322    {
323        match self.data {
324            QueryData::SortedVec { items, .. } => {
325                let mut groups: HashMap<K, Vec<T>> = HashMap::new();
326                for item in items {
327                    let key = key_selector(&item);
328                    groups.entry(key).or_default().push(item);
329                }
330                groups
331            }
332            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
333        }
334    }
335
336    /// Group sorted elements and apply an aggregation to each group
337    #[inline]
338    pub fn group_by_aggregate<K, R, FK, FA>(self, key_selector: FK, aggregator: FA) -> HashMap<K, R>
339    where
340        FK: Fn(&T) -> K,
341        FA: Fn(&[T]) -> R,
342        K: Eq + Hash,
343    {
344        let groups = self.group_by(key_selector);
345        groups
346            .into_iter()
347            .map(|(k, v)| (k, aggregator(&v)))
348            .collect()
349    }
350
351    /// Remove duplicate elements from sorted collection
352    ///
353    /// Converts to Filtered state with duplicates removed.
354    #[inline]
355    pub fn distinct(self) -> QueryBuilder<T, Filtered>
356    where
357        T: HashEqBound + Clone,
358    {
359        match self.data {
360            QueryData::SortedVec { items, .. } => {
361                let mut seen = HashSet::new();
362                let filtered = items.into_iter().filter(move |item| {
363                    if seen.contains(item) {
364                        false
365                    } else {
366                        seen.insert(item.clone());
367                        true
368                    }
369                });
370
371                QueryBuilder {
372                    data: QueryData::Iterator(Box::new(filtered)),
373                    _state: PhantomData,
374                }
375            }
376            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
377        }
378    }
379
380    /// Remove duplicate elements based on a key selector from sorted collection
381    #[inline]
382    pub fn distinct_by<K, F>(self, key_selector: F) -> QueryBuilder<T, Filtered>
383    where
384        F: Fn(&T) -> K + 'static,
385        K: Eq + Hash + 'static,
386    {
387        match self.data {
388            QueryData::SortedVec { items, .. } => {
389                let mut seen = HashSet::new();
390                let filtered = items.into_iter().filter(move |item| {
391                    let key = key_selector(item);
392                    if seen.contains(&key) {
393                        false
394                    } else {
395                        seen.insert(key);
396                        true
397                    }
398                });
399
400                QueryBuilder {
401                    data: QueryData::Iterator(Box::new(filtered)),
402                    _state: PhantomData,
403                }
404            }
405            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
406        }
407    }
408
409    /// Reverse the sorted iteration order
410    #[inline]
411    pub fn reverse(self) -> QueryBuilder<T, Filtered> {
412        match self.data {
413            QueryData::SortedVec { mut items, .. } => {
414                items.reverse();
415
416                QueryBuilder {
417                    data: QueryData::Iterator(Box::new(items.into_iter())),
418                    _state: PhantomData,
419                }
420            }
421            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
422        }
423    }
424
425    /// Split sorted elements into fixed-size chunks
426    ///
427    /// # Panics
428    ///
429    /// Panics if `size` is 0.
430    #[inline]
431    pub fn chunk(self, size: usize) -> QueryBuilder<Vec<T>, Filtered> {
432        assert!(size > 0, "chunk size must be greater than 0");
433
434        match self.data {
435            QueryData::SortedVec { items, .. } => {
436                let chunk_iter = ChunkIterator {
437                    inner: items.into_iter(),
438                    chunk_size: size,
439                };
440
441                QueryBuilder {
442                    data: QueryData::Iterator(Box::new(chunk_iter)),
443                    _state: PhantomData,
444                }
445            }
446            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
447        }
448    }
449
450    /// Create sliding windows over sorted elements
451    ///
452    /// # Panics
453    ///
454    /// Panics if `size` is 0.
455    #[inline]
456    pub fn window(self, size: usize) -> QueryBuilder<Vec<T>, Filtered>
457    where
458        T: Clone,
459    {
460        assert!(size > 0, "window size must be greater than 0");
461
462        match self.data {
463            QueryData::SortedVec { items, .. } => {
464                let window_iter = WindowIterator {
465                    buffer: VecDeque::new(),
466                    inner: Box::new(items.into_iter()),
467                    window_size: size,
468                    finished: false,
469                };
470
471                QueryBuilder {
472                    data: QueryData::Iterator(Box::new(window_iter)),
473                    _state: PhantomData,
474                }
475            }
476            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
477        }
478    }
479
480    /// Zip this sorted query with another iterable
481    #[inline]
482    pub fn zip<U, I>(self, other: I) -> QueryBuilder<(T, U), Filtered>
483    where
484        U: 'static,
485        I: IntoIterator<Item = U> + 'static,
486        I::IntoIter: 'static,
487    {
488        match self.data {
489            QueryData::SortedVec { items, .. } => {
490                let zipped = items.into_iter().zip(other);
491
492                QueryBuilder {
493                    data: QueryData::Iterator(Box::new(zipped)),
494                    _state: PhantomData,
495                }
496            }
497            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
498        }
499    }
500
501    /// Add indices to sorted elements
502    #[inline]
503    pub fn enumerate(self) -> QueryBuilder<(usize, T), Filtered> {
504        match self.data {
505            QueryData::SortedVec { items, .. } => {
506                let enumerated = items.into_iter().enumerate();
507
508                QueryBuilder {
509                    data: QueryData::Iterator(Box::new(enumerated)),
510                    _state: PhantomData,
511                }
512            }
513            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
514        }
515    }
516
517    /// Partition sorted elements into two collections
518    #[inline]
519    pub fn partition<F>(self, predicate: F) -> (Vec<T>, Vec<T>)
520    where
521        F: Fn(&T) -> bool,
522    {
523        match self.data {
524            QueryData::SortedVec { items, .. } => {
525                let mut left = Vec::new();
526                let mut right = Vec::new();
527
528                for item in items {
529                    if predicate(&item) {
530                        left.push(item);
531                    } else {
532                        right.push(item);
533                    }
534                }
535
536                (left, right)
537            }
538            QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
539        }
540    }
541}