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