1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
mod alternate; pub use alternate::*; /// Provides additional convenience methods to the `Iterator` trait and its implementors. pub trait ExoticIteratorExt: Iterator + Sized { /// Consumes the iterator, counting the number of items that pass the predicate and returns true iff there were at least `n` passing items. /// /// # Example /// ```rust /// use exotic_iter::*; /// let very_few_twos = vec![1, 2, 3, 4, 5, 6]; /// let lots_of_twos = vec![2, 3, 2, 4, 2, 5]; /// assert_eq!(false, very_few_twos.into_iter().at_least(3_usize, |n| *n == 2)); /// assert_eq!(true, lots_of_twos.into_iter().at_least(3_usize, |n| *n == 2)); /// ``` fn at_least<P: FnMut(&Self::Item) -> bool>(self, n: usize, predicate: P) -> bool; /// Consumes the iterator, counting the number of items that pass the predicate and returns true iff there were no more than `n` passing items. /// /// # Example /// ```rust /// use exotic_iter::*; /// let just_enough_twos = vec![1, 1, 2, 2, 3, 3]; /// let too_many_twos = vec![2, 2, 2, 2, 2, 2]; /// assert_eq!(true, just_enough_twos.into_iter().at_most(2_usize, |n| *n == 2)); /// assert_eq!(false, too_many_twos.into_iter().at_most(2_usize, |n| *n == 2)); /// ``` fn at_most<P: FnMut(&Self::Item) -> bool>(self, n: usize, predicate: P) -> bool; /// Consumes the iterator, counting the number of items that pass the predicate and returns true iff there were exactly `n` passing items. /// /// # Example /// ```rust /// use exotic_iter::*; /// let no_digits = "deadbeef"; /// let two_digits = "deadb33f"; /// let three_digits = "d3adb33f"; /// assert_eq!(false, no_digits.chars().exactly_n(2_usize, |c| c.is_ascii_digit())); /// assert_eq!(true, two_digits.chars().exactly_n(2_usize, |c| c.is_ascii_digit())); /// assert_eq!(false, three_digits.chars().exactly_n(2_usize, |c| c.is_ascii_digit())); /// ``` fn exactly_n<P: FnMut(&Self::Item) -> bool>(self, n: usize, predicate: P) -> bool; /// Consumes the iterator, counting the number of items that pass each predicate and returns true iff /// there were exactly `m` passing items for the `predicate_m`, and exactly `n` passing items for `predicate_n`. /// /// # Example /// ```rust /// use exotic_iter::*; /// let more_digits = "abc12345"; /// let balanced_digits = "abcd1234"; /// let more_letters = "abcde123"; /// assert_eq!(false, more_digits.chars().exactly_m_n(4_usize, |c| c.is_ascii_alphabetic(), 4_usize, |c| c.is_ascii_digit())); /// assert_eq!(true, balanced_digits.chars().exactly_m_n(4_usize, |c| c.is_ascii_alphabetic(), 4_usize, |c| c.is_ascii_digit())); /// assert_eq!(false, more_letters.chars().exactly_m_n(4_usize, |c| c.is_ascii_alphabetic(), 4_usize, |c| c.is_ascii_digit())); /// ``` fn exactly_m_n<Pm: FnMut(&Self::Item) -> bool, Pn: FnMut(&Self::Item) -> bool>(self, m: usize, predicate_m: Pm, n: usize, predicate_n: Pn) -> bool; /// Consumes the iterator and returns true iff either all of the items in the iterator passed the predicate, or none of them passed. /// Returns early on the first mixed result. /// /// # Example /// ```rust /// use exotic_iter::*; /// let all_true = vec![true, true, true]; /// let some_true = vec![true, false, true]; /// let none_true = vec![false, false, false]; /// assert_eq!(true, all_true.into_iter().all_or_none(|b| *b)); /// assert_eq!(false, some_true.into_iter().all_or_none(|b| *b)); /// assert_eq!(true, none_true.into_iter().all_or_none(|b| *b)); /// ``` fn all_or_none<P: FnMut(&Self::Item) -> bool>(self, predicate: P) -> bool; /// Consumes the iterator and returns true if exactly half of the items passed the predicate; as all things should be. /// /// # Example /// ```rust /// use exotic_iter::*; /// let two_even = vec![1, 2, 3, 4]; /// let three_even = vec![1, 2, 4, 6]; /// assert_eq!(true, two_even.into_iter().perfectly_balanced(|n| *n % 2 == 0)); /// assert_eq!(false, three_even.into_iter().perfectly_balanced(|n| *n % 2 == 0)); /// ``` fn perfectly_balanced<P: FnMut(&Self::Item) -> bool>(self, predicate: P) -> bool; /// Creates an iterator that alternates between items from `self` and `other`, with `self` providing the first value. /// Short-circuits at the first `None` returned, even if one of the iterators still has values left. /// /// # Example /// ```rust /// use exotic_iter::*; /// let odd_numbers = vec![1, 3]; /// let even_numbers = vec![2, 4]; /// let mut iter = odd_numbers.iter().alternate(even_numbers.iter()); /// assert_eq!(Some(&1), iter.next()); /// assert_eq!(Some(&2), iter.next()); /// assert_eq!(Some(&3), iter.next()); /// assert_eq!(Some(&4), iter.next()); /// assert_eq!(None, iter.next()); /// ``` fn alternate<U: IntoIterator<Item = Self::Item>>(self, other: U) -> Alternate<Self, U::IntoIter>; } impl<T: Iterator> ExoticIteratorExt for T { #[inline] fn at_least<P: FnMut(&Self::Item) -> bool>(self, n: usize, predicate: P) -> bool { self.filter(predicate).take(n).count() == n } #[inline] fn at_most<P: FnMut(&Self::Item) -> bool>(self, n: usize, predicate: P) -> bool { self.filter(predicate).skip(n).count() == 0 } fn exactly_n<P: FnMut(&Self::Item) -> bool>(self, n: usize, predicate: P) -> bool { let mut predicate = predicate; let mut count: usize = 0; for item in self { if predicate(&item) { count += 1; } if count > n { return false } } count == n } fn exactly_m_n< Pm: FnMut(&Self::Item) -> bool, Pn: FnMut(&Self::Item) -> bool, >(self, m: usize, predicate_m: Pm, n: usize, predicate_n: Pn) -> bool { let mut predicate_m = predicate_m; let mut predicate_n = predicate_n; let mut count_m: usize = 0; let mut count_n: usize = 0; for item in self { if predicate_m(&item) { count_m += 1; } if predicate_n(&item) { count_n += 1; } if count_m > m || count_n > n { return false } } (count_m, count_n) == (m, n) } fn perfectly_balanced<P: FnMut(&Self::Item) -> bool>(self, predicate: P) -> bool { let mut predicate = predicate; let mut count: usize = 0; let mut total: usize = 0; for item in self { total += 1; if predicate(&item) { count += 1; } } total % 2 == 0 && total / 2 == count } fn all_or_none<P: FnMut(&Self::Item) -> bool>(self, predicate: P) -> bool { let mut predicate = predicate; let mut has_pass = false; let mut has_fail = false; for item in self { if predicate(&item) { has_pass = true; } else { has_fail = true; } if has_pass && has_fail { return false } } true } fn alternate<U: IntoIterator<Item = Self::Item>>(self, other: U) -> Alternate<Self, <U as IntoIterator>::IntoIter> { Alternate::new(self, other.into_iter()) } }