Skip to main content

polars_utils/itertools/
mod.rs

1use std::cmp::Ordering;
2use std::fmt::Write;
3
4use crate::IdxSize;
5
6pub mod enumerate_idx;
7pub mod iters_eq;
8pub mod zip_eq;
9
10pub use enumerate_idx::EnumerateIdx;
11pub use zip_eq::{ZipEq, zip_eq};
12
13/// Utility extension trait of iterator methods.
14pub trait Itertools: Iterator {
15    /// Equivalent to `.collect::<Vec<_>>()`.
16    fn collect_vec(self) -> Vec<Self::Item>
17    where
18        Self: Sized,
19    {
20        self.collect()
21    }
22
23    /// Equivalent to `.collect::<Result<_, _>>()`.
24    fn try_collect<T, U, E>(self) -> Result<U, E>
25    where
26        Self: Sized + Iterator<Item = Result<T, E>>,
27        Result<U, E>: FromIterator<Result<T, E>>,
28    {
29        self.collect()
30    }
31
32    /// Equivalent to `.collect::<Result<Vec<_>, _>>()`.
33    fn try_collect_vec<T, U, E>(self) -> Result<Vec<U>, E>
34    where
35        Self: Sized + Iterator<Item = Result<T, E>>,
36        Result<Vec<U>, E>: FromIterator<Result<T, E>>,
37    {
38        self.collect()
39    }
40
41    fn enumerate_idx(self) -> EnumerateIdx<Self, IdxSize>
42    where
43        Self: Sized,
44    {
45        EnumerateIdx::new(self)
46    }
47
48    fn enumerate_u32(self) -> EnumerateIdx<Self, u32>
49    where
50        Self: Sized,
51    {
52        EnumerateIdx::new(self)
53    }
54
55    fn all_equal(mut self) -> bool
56    where
57        Self: Sized,
58        Self::Item: PartialEq,
59    {
60        match self.next() {
61            None => true,
62            Some(a) => self.all(|x| a == x),
63        }
64    }
65
66    // Stable copy of the unstable eq_by from the stdlib.
67    fn eq_by_<I, F>(mut self, other: I, mut eq: F) -> bool
68    where
69        Self: Sized,
70        I: IntoIterator,
71        F: FnMut(Self::Item, I::Item) -> bool,
72    {
73        let mut other = other.into_iter();
74        loop {
75            match (self.next(), other.next()) {
76                (None, None) => return true,
77                (None, Some(_)) => return false,
78                (Some(_), None) => return false,
79                (Some(l), Some(r)) => {
80                    if eq(l, r) {
81                        continue;
82                    } else {
83                        return false;
84                    }
85                },
86            }
87        }
88    }
89
90    // Stable copy of the unstable partial_cmp_by from the stdlib.
91    fn partial_cmp_by_<I, F>(mut self, other: I, mut partial_cmp: F) -> Option<Ordering>
92    where
93        Self: Sized,
94        I: IntoIterator,
95        F: FnMut(Self::Item, I::Item) -> Option<Ordering>,
96    {
97        let mut other = other.into_iter();
98        loop {
99            match (self.next(), other.next()) {
100                (None, None) => return Some(Ordering::Equal),
101                (None, Some(_)) => return Some(Ordering::Less),
102                (Some(_), None) => return Some(Ordering::Greater),
103                (Some(l), Some(r)) => match partial_cmp(l, r) {
104                    Some(Ordering::Equal) => continue,
105                    ord => return ord,
106                },
107            }
108        }
109    }
110
111    fn join(&mut self, sep: &str) -> String
112    where
113        Self::Item: std::fmt::Display,
114    {
115        match self.next() {
116            None => String::new(),
117            Some(first_elt) => {
118                // Estimate lower bound of capacity needed.
119                let (lower, _) = self.size_hint();
120                let mut result = String::with_capacity(sep.len() * lower);
121                write!(&mut result, "{}", first_elt).unwrap();
122                self.for_each(|elt| {
123                    result.push_str(sep);
124                    write!(&mut result, "{}", elt).unwrap();
125                });
126                result
127            },
128        }
129    }
130
131    /// Zips two iterators but **panics** if they are not of the same length.
132    fn zip_eq<I>(self, other: I) -> ZipEq<Self, I::IntoIter>
133    where
134        Self: Sized,
135        I: IntoIterator,
136    {
137        zip_eq(self, other)
138    }
139}
140
141impl<T: Iterator + ?Sized> Itertools for T {}