tea_map/
lib.rs

1mod valid_iter;
2mod vec_map;
3
4use tea_core::prelude::*;
5pub use valid_iter::{Keep, MapValidBasic};
6pub use vec_map::MapValidVec;
7/// A trait for basic mapping operations on trusted length iterators.
8///
9/// This trait provides methods for common operations like absolute value and shifting,
10/// which can be applied to iterators with a known length.
11pub trait MapBasic: TrustedLen
12where
13    Self: Sized,
14{
15    /// Applies the absolute value function to each element in the iterator.
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// use tea_core::prelude::*;
21    /// use tea_map::MapBasic;
22    ///
23    /// let v = vec![-1, 2, -3, 4, -5];
24    /// let result: Vec<_> = v.titer().abs().collect();
25    /// assert_eq!(result, vec![1, 2, 3, 4, 5]);
26    /// ```
27    #[inline]
28    fn abs(self) -> impl TrustedLen<Item = Self::Item>
29    where
30        Self::Item: Number,
31    {
32        self.map(|v| v.abs())
33    }
34
35    /// Shifts the elements of the iterator by `n` positions, filling in with the provided `value`.
36    ///
37    /// - If `n` is positive, shifts right and prepends `value`.
38    /// - If `n` is negative, shifts left and appends `value`.
39    /// - If `n` is zero, returns the original iterator.
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use tea_core::prelude::*;
45    /// use tea_map::MapBasic;
46    ///
47    /// let v = vec![1, 2, 3, 4, 5];
48    /// let result: Vec<_> = v.titer().shift(2, 0).collect();
49    /// assert_eq!(result, vec![0, 0, 1, 2, 3]);
50    ///
51    /// let result: Vec<_> = v.titer().shift(-2, 0).collect();
52    /// assert_eq!(result, vec![3, 4, 5, 0, 0]);
53    /// ```
54    fn shift<'a>(self, n: i32, value: Self::Item) -> Box<dyn TrustedLen<Item = Self::Item> + 'a>
55    where
56        Self::Item: Clone + 'a,
57        Self: Sized + 'a,
58    {
59        let len = self.len();
60        let n_abs = n.unsigned_abs() as usize;
61        match n {
62            n if n > 0 => Box::new(TrustIter::new(
63                std::iter::repeat_n(value, n_abs).chain(self.take(len - n_abs)),
64                len,
65            )),
66            n if n < 0 => Box::new(TrustIter::new(
67                self.skip(n_abs).chain(std::iter::repeat_n(value, n_abs)),
68                len,
69            )),
70            _ => Box::new(self),
71        }
72    }
73}
74
75impl<I: TrustedLen> MapBasic for I {}
76
77#[cfg(test)]
78mod test {
79    use tea_core::testing::assert_vec1d_equal_numeric;
80
81    use super::*;
82    #[test]
83    fn test_abs() {
84        let v = vec![1, -2, 3, -4, 5];
85        let res: Vec<_> = v.titer().abs().vabs().collect_trusted_vec1();
86        assert_eq!(res, vec![1, 2, 3, 4, 5]);
87        let v = vec![Some(1), Some(-2), None, Some(-4), Some(5)];
88        let res: Vec<_> = v.titer().vabs().collect_trusted_vec1();
89        assert_eq!(res, vec![Some(1), Some(2), None, Some(4), Some(5)]);
90    }
91
92    #[test]
93    fn test_shift() {
94        // test shift on empty vec
95        let v: Vec<f64> = vec![];
96        let res: Vec<_> = v.titer().vshift(2, None).collect_trusted_vec1();
97        assert_eq!(res, vec![]);
98        let v = vec![1., 2., 3., 4., 5.];
99        let res: Vec<_> = v.titer().vshift(2, None).collect_trusted_vec1();
100        assert_vec1d_equal_numeric(&res, &vec![f64::NAN, f64::NAN, 1., 2., 3.], None);
101        let v = vec![1, 2, 3, 4, 5];
102        let res: Vec<_> = v
103            .titer()
104            .vshift(-2, Some(0))
105            .vshift(0, Some(0))
106            .collect_trusted_to_vec();
107        assert_eq!(res, vec![3, 4, 5, 0, 0]);
108    }
109}