polars-utils 0.54.1

Private utils for the Polars DataFrame library
Documentation
use std::cmp::Ordering;
use std::fmt::Write;

use crate::IdxSize;

pub mod enumerate_idx;
pub mod zip_eq;

pub use enumerate_idx::EnumerateIdx;
pub use zip_eq::{ZipEq, zip_eq};

/// Utility extension trait of iterator methods.
pub trait Itertools: Iterator {
    /// Equivalent to `.collect::<Vec<_>>()`.
    fn collect_vec(self) -> Vec<Self::Item>
    where
        Self: Sized,
    {
        self.collect()
    }

    /// Equivalent to `.collect::<Result<_, _>>()`.
    fn try_collect<T, U, E>(self) -> Result<U, E>
    where
        Self: Sized + Iterator<Item = Result<T, E>>,
        Result<U, E>: FromIterator<Result<T, E>>,
    {
        self.collect()
    }

    /// Equivalent to `.collect::<Result<Vec<_>, _>>()`.
    fn try_collect_vec<T, U, E>(self) -> Result<Vec<U>, E>
    where
        Self: Sized + Iterator<Item = Result<T, E>>,
        Result<Vec<U>, E>: FromIterator<Result<T, E>>,
    {
        self.collect()
    }

    fn enumerate_idx(self) -> EnumerateIdx<Self, IdxSize>
    where
        Self: Sized,
    {
        EnumerateIdx::new(self)
    }

    fn enumerate_u32(self) -> EnumerateIdx<Self, u32>
    where
        Self: Sized,
    {
        EnumerateIdx::new(self)
    }

    fn all_equal(mut self) -> bool
    where
        Self: Sized,
        Self::Item: PartialEq,
    {
        match self.next() {
            None => true,
            Some(a) => self.all(|x| a == x),
        }
    }

    // Stable copy of the unstable eq_by from the stdlib.
    fn eq_by_<I, F>(mut self, other: I, mut eq: F) -> bool
    where
        Self: Sized,
        I: IntoIterator,
        F: FnMut(Self::Item, I::Item) -> bool,
    {
        let mut other = other.into_iter();
        loop {
            match (self.next(), other.next()) {
                (None, None) => return true,
                (None, Some(_)) => return false,
                (Some(_), None) => return false,
                (Some(l), Some(r)) => {
                    if eq(l, r) {
                        continue;
                    } else {
                        return false;
                    }
                },
            }
        }
    }

    // Stable copy of the unstable partial_cmp_by from the stdlib.
    fn partial_cmp_by_<I, F>(mut self, other: I, mut partial_cmp: F) -> Option<Ordering>
    where
        Self: Sized,
        I: IntoIterator,
        F: FnMut(Self::Item, I::Item) -> Option<Ordering>,
    {
        let mut other = other.into_iter();
        loop {
            match (self.next(), other.next()) {
                (None, None) => return Some(Ordering::Equal),
                (None, Some(_)) => return Some(Ordering::Less),
                (Some(_), None) => return Some(Ordering::Greater),
                (Some(l), Some(r)) => match partial_cmp(l, r) {
                    Some(Ordering::Equal) => continue,
                    ord => return ord,
                },
            }
        }
    }

    fn join(&mut self, sep: &str) -> String
    where
        Self::Item: std::fmt::Display,
    {
        match self.next() {
            None => String::new(),
            Some(first_elt) => {
                // Estimate lower bound of capacity needed.
                let (lower, _) = self.size_hint();
                let mut result = String::with_capacity(sep.len() * lower);
                write!(&mut result, "{}", first_elt).unwrap();
                self.for_each(|elt| {
                    result.push_str(sep);
                    write!(&mut result, "{}", elt).unwrap();
                });
                result
            },
        }
    }

    /// Zips two iterators but **panics** if they are not of the same length.
    fn zip_eq<I>(self, other: I) -> ZipEq<Self, I::IntoIter>
    where
        Self: Sized,
        I: IntoIterator,
    {
        zip_eq(self, other)
    }
}

impl<T: Iterator + ?Sized> Itertools for T {}