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(value)
64                    .take(n_abs)
65                    .chain(self.take(len - n_abs)),
66                len,
67            )),
68            n if n < 0 => Box::new(TrustIter::new(
69                self.skip(n_abs).chain(std::iter::repeat(value).take(n_abs)),
70                len,
71            )),
72            _ => Box::new(self),
73        }
74    }
75}
76
77impl<I: TrustedLen> MapBasic for I {}
78
79#[cfg(test)]
80mod test {
81    use tea_core::testing::assert_vec1d_equal_numeric;
82
83    use super::*;
84    #[test]
85    fn test_abs() {
86        let v = vec![1, -2, 3, -4, 5];
87        let res: Vec<_> = v.titer().abs().vabs().collect_trusted_vec1();
88        assert_eq!(res, vec![1, 2, 3, 4, 5]);
89        let v = vec![Some(1), Some(-2), None, Some(-4), Some(5)];
90        let res: Vec<_> = v.titer().vabs().collect_trusted_vec1();
91        assert_eq!(res, vec![Some(1), Some(2), None, Some(4), Some(5)]);
92    }
93
94    #[test]
95    fn test_shift() {
96        // test shift on empty vec
97        let v: Vec<f64> = vec![];
98        let res: Vec<_> = v.titer().vshift(2, None).collect_trusted_vec1();
99        assert_eq!(res, vec![]);
100        let v = vec![1., 2., 3., 4., 5.];
101        let res: Vec<_> = v.titer().vshift(2, None).collect_trusted_vec1();
102        assert_vec1d_equal_numeric(&res, &vec![f64::NAN, f64::NAN, 1., 2., 3.], None);
103        let v = vec![1, 2, 3, 4, 5];
104        let res: Vec<_> = v
105            .titer()
106            .vshift(-2, Some(0))
107            .vshift(0, Some(0))
108            .collect_trusted_to_vec();
109        assert_eq!(res, vec![3, 4, 5, 0, 0]);
110    }
111}