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