use std::iter::Cycle; use std::iter::Fuse; use std::iter::FusedIterator;
usecrate::size_hint;
// `HomogeneousTuple` is a public facade for `TupleCollect`, allowing // tuple-related methods to be used by clients in generic contexts, while // hiding the implementation details of `TupleCollect`. // See https://github.com/rust-itertools/itertools/issues/387
/// Implemented for homogeneous tuples of size up to 12. pubtrait HomogeneousTuple: TupleCollect {}
impl<T: TupleCollect> HomogeneousTuple for T {}
/// An iterator over a incomplete tuple. /// /// See [`.tuples()`](crate::Itertools::tuples) and /// [`Tuples::into_buffer()`]. #[derive(Clone, Debug)] pubstruct TupleBuffer<T> where
T: HomogeneousTuple,
{
cur: usize,
buf: T::Buffer,
}
fn size_hint(&self) -> (usize, Option<usize>) { let buffer = &self.buf.as_ref()[self.cur..]; let len = if buffer.is_empty() { 0
} else {
buffer
.iter()
.position(|x| x.is_none())
.unwrap_or(buffer.len())
};
(len, Some(len))
}
}
impl<T> ExactSizeIterator for TupleBuffer<T> where T: HomogeneousTuple {}
/// An iterator that groups the items in tuples of a specific size. /// /// See [`.tuples()`](crate::Itertools::tuples) for more information. #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct Tuples<I, T> where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
iter: Fuse<I>,
buf: T::Buffer,
}
/// Create a new tuples iterator. pub fn tuples<I, T>(iter: I) -> Tuples<I, T> where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
Tuples {
iter: iter.fuse(),
buf: Default::default(),
}
}
impl<I, T> Iterator for Tuples<I, T> where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{ type Item = T;
fn size_hint(&self) -> (usize, Option<usize>) { // The number of elts we've drawn from the underlying iterator, but have // not yet produced as a tuple. let buffered = T::buffer_len(&self.buf); // To that, we must add the size estimates of the underlying iterator. let (unbuffered_lo, unbuffered_hi) = self.iter.size_hint(); // The total low estimate is the sum of the already-buffered elements, // plus the low estimate of remaining unbuffered elements, divided by // the tuple size. let total_lo = add_then_div(unbuffered_lo, buffered, T::num_items()).unwrap_or(usize::MAX); // And likewise for the total high estimate, but using the high estimate // of the remaining unbuffered elements. let total_hi = unbuffered_hi.and_then(|hi| add_then_div(hi, buffered, T::num_items()));
(total_lo, total_hi)
}
}
/// `(n + a) / d` avoiding overflow when possible, returns `None` if it overflows.
fn add_then_div(n: usize, a: usize, d: usize) -> Option<usize> {
debug_assert_ne!(d, 0);
(n / d).checked_add(a / d)?.checked_add((n % d + a % d) / d)
}
impl<I, T> ExactSizeIterator for Tuples<I, T> where
I: ExactSizeIterator<Item = T::Item>,
T: HomogeneousTuple,
{
}
impl<I, T> Tuples<I, T> where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{ /// Return a buffer with the produced items that was not enough to be grouped in a tuple. /// /// ``` /// use itertools::Itertools; /// /// let mut iter = (0..5).tuples(); /// assert_eq!(Some((0, 1, 2)), iter.next()); /// assert_eq!(None, iter.next()); /// itertools::assert_equal(vec![3, 4], iter.into_buffer()); /// ``` pub fn into_buffer(self) -> TupleBuffer<T> {
TupleBuffer::new(self.buf)
}
}
/// An iterator over all contiguous windows that produces tuples of a specific size. /// /// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more /// information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] pubstruct TupleWindows<I, T> where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
iter: I,
last: Option<T>,
}
/// Create a new tuple windows iterator. pub fn tuple_windows<I, T>(iter: I) -> TupleWindows<I, T> where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
T::Item: Clone,
{
TupleWindows { last: None, iter }
}
impl<I, T> Iterator for TupleWindows<I, T> where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple + Clone,
T::Item: Clone,
{ type Item = T;
fn size_hint(&self) -> (usize, Option<usize>) { letmut sh = self.iter.size_hint(); // Adjust the size hint at the beginning // OR when `num_items == 1` (but it does not change the size hint). ifself.last.is_none() {
sh = size_hint::sub_scalar(sh, T::num_items() - 1);
}
sh
}
}
impl<I, T> ExactSizeIterator for TupleWindows<I, T> where
I: ExactSizeIterator<Item = T::Item>,
T: HomogeneousTuple + Clone,
T::Item: Clone,
{
}
impl<I, T> FusedIterator for TupleWindows<I, T> where
I: FusedIterator<Item = T::Item>,
T: HomogeneousTuple + Clone,
T::Item: Clone,
{
}
/// An iterator over all windows, wrapping back to the first elements when the /// window would otherwise exceed the length of the iterator, producing tuples /// of a specific size. /// /// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more /// information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Debug, Clone)] pubstruct CircularTupleWindows<I, T> where
I: Iterator<Item = T::Item> + Clone,
T: TupleCollect + Clone,
{
iter: TupleWindows<Cycle<I>, T>,
len: usize,
}
pub fn circular_tuple_windows<I, T>(iter: I) -> CircularTupleWindows<I, T> where
I: Iterator<Item = T::Item> + Clone + ExactSizeIterator,
T: TupleCollect + Clone,
T::Item: Clone,
{ let len = iter.len(); let iter = tuple_windows(iter.cycle());
CircularTupleWindows { iter, len }
}
impl<I, T> Iterator for CircularTupleWindows<I, T> where
I: Iterator<Item = T::Item> + Clone,
T: TupleCollect + Clone,
T::Item: Clone,
{ type Item = T;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.