mod coalesce; pub(crate) mod map; mod multi_product; pubuseself::coalesce::*; pubuseself::map::{map_into, map_ok, MapInto, MapOk}; #[cfg(feature = "use_alloc")] pubuseself::multi_product::*;
usecrate::size_hint::{self, SizeHint}; use std::fmt; use std::iter::{Enumerate, FromIterator, Fuse, FusedIterator}; use std::marker::PhantomData;
/// An iterator adaptor that alternates elements from two iterators until both /// run out. /// /// This iterator is *fused*. /// /// See [`.interleave()`](crate::Itertools::interleave) for more information. #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct Interleave<I, J> {
i: Fuse<I>,
j: Fuse<J>,
next_coming_from_j: bool,
}
/// Create an iterator that interleaves elements in `i` and `j`. /// /// [`IntoIterator`] enabled version of [`Itertools::interleave`](crate::Itertools::interleave). pubfn interleave<I, J>(
i: I,
j: J,
) -> Interleave<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
{
Interleave {
i: i.into_iter().fuse(),
j: j.into_iter().fuse(),
next_coming_from_j: false,
}
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B where
F: FnMut(B, Self::Item) -> B,
{ letSelf { mut i, mut j,
next_coming_from_j,
} = self; if next_coming_from_j { match j.next() {
Some(y) => init = f(init, y),
None => return i.fold(init, f),
}
} let res = i.try_fold(init, |mut acc, x| {
acc = f(acc, x); match j.next() {
Some(y) => Ok(f(acc, y)),
None => Err(acc),
}
}); match res {
Ok(acc) => j.fold(acc, f),
Err(acc) => i.fold(acc, f),
}
}
}
impl<I, J> FusedIterator for Interleave<I, J> where
I: Iterator,
J: Iterator<Item = I::Item>,
{
}
/// An iterator adaptor that alternates elements from the two iterators until /// one of them runs out. /// /// This iterator is *fused*. /// /// See [`.interleave_shortest()`](crate::Itertools::interleave_shortest) /// for more information. #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct InterleaveShortest<I, J> where
I: Iterator,
J: Iterator<Item = I::Item>,
{
i: I,
j: J,
next_coming_from_j: bool,
}
/// Create a new `InterleaveShortest` iterator. pubfn interleave_shortest<I, J>(i: I, j: J) -> InterleaveShortest<I, J> where
I: Iterator,
J: Iterator<Item = I::Item>,
{
InterleaveShortest {
i,
j,
next_coming_from_j: false,
}
}
impl<I, J> Iterator for InterleaveShortest<I, J> where
I: Iterator,
J: Iterator<Item = I::Item>,
{ type Item = I::Item;
#[inline] fn next(&mutself) -> Option<Self::Item> { let e = ifself.next_coming_from_j { self.j.next()
} else { self.i.next()
}; if e.is_some() { self.next_coming_from_j = !self.next_coming_from_j;
}
e
}
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { let (curr_hint, next_hint) = { let i_hint = self.i.size_hint(); let j_hint = self.j.size_hint(); ifself.next_coming_from_j {
(j_hint, i_hint)
} else {
(i_hint, j_hint)
}
}; let (curr_lower, curr_upper) = curr_hint; let (next_lower, next_upper) = next_hint; let (combined_lower, combined_upper) =
size_hint::mul_scalar(size_hint::min(curr_hint, next_hint), 2); let lower = if curr_lower > next_lower {
combined_lower + 1
} else {
combined_lower
}; let upper = { let extra_elem = match (curr_upper, next_upper) {
(_, None) => false,
(None, Some(_)) => true,
(Some(curr_max), Some(next_max)) => curr_max > next_max,
}; if extra_elem {
combined_upper.and_then(|x| x.checked_add(1))
} else {
combined_upper
}
};
(lower, upper)
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B where
F: FnMut(B, Self::Item) -> B,
{ letSelf { mut i, mut j,
next_coming_from_j,
} = self; if next_coming_from_j { match j.next() {
Some(y) => init = f(init, y),
None => return init,
}
} let res = i.try_fold(init, |mut acc, x| {
acc = f(acc, x); match j.next() {
Some(y) => Ok(f(acc, y)),
None => Err(acc),
}
}); match res {
Ok(val) => val,
Err(val) => val,
}
}
}
impl<I, J> FusedIterator for InterleaveShortest<I, J> where
I: FusedIterator,
J: FusedIterator<Item = I::Item>,
{
}
#[derive(Clone, Debug)] /// An iterator adaptor that allows putting back a single /// item to the front of the iterator. /// /// Iterator element type is `I::Item`. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct PutBack<I> where
I: Iterator,
{
top: Option<I::Item>,
iter: I,
}
/// Create an iterator where you can put back a single item pubfn put_back<I>(iterable: I) -> PutBack<I::IntoIter> where
I: IntoIterator,
{
PutBack {
top: None,
iter: iterable.into_iter(),
}
}
impl<I> PutBack<I> where
I: Iterator,
{ /// put back value `value` (builder method) pubfn with_value(mutself, value: I::Item) -> Self { self.put_back(value); self
}
/// Split the `PutBack` into its parts. #[inline] pubfn into_parts(self) -> (Option<I::Item>, I) { letSelf { top, iter } = self;
(top, iter)
}
/// Put back a single value to the front of the iterator. /// /// If a value is already in the put back slot, it is returned. #[inline] pubfn put_back(&mutself, x: I::Item) -> Option<I::Item> { self.top.replace(x)
}
}
impl<I> Iterator for PutBack<I> where
I: Iterator,
{ type Item = I::Item; #[inline] fn next(&mutself) -> Option<Self::Item> { matchself.top {
None => self.iter.next(), refmut some => some.take(),
}
} #[inline] fn size_hint(&self) -> (usize, Option<usize>) { // Not ExactSizeIterator because size may be larger than usize
size_hint::add_scalar(self.iter.size_hint(), self.top.is_some() as usize)
}
#[derive(Debug, Clone)] /// An iterator adaptor that iterates over the cartesian product of /// the element sets of two iterators `I` and `J`. /// /// Iterator element type is `(I::Item, J::Item)`. /// /// See [`.cartesian_product()`](crate::Itertools::cartesian_product) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct Product<I, J> where
I: Iterator,
{
a: I, /// `a_cur` is `None` while no item have been taken out of `a` (at definition). /// Then `a_cur` will be `Some(Some(item))` until `a` is exhausted, /// in which case `a_cur` will be `Some(None)`.
a_cur: Option<Option<I::Item>>,
b: J,
b_orig: J,
}
/// Create a new cartesian product iterator /// /// Iterator element type is `(I::Item, J::Item)`. pubfn cartesian_product<I, J>(i: I, j: J) -> Product<I, J> where
I: Iterator,
J: Clone + Iterator,
I::Item: Clone,
{
Product {
a_cur: None,
a: i,
b: j.clone(),
b_orig: j,
}
}
impl<I, J> Iterator for Product<I, J> where
I: Iterator,
J: Clone + Iterator,
I::Item: Clone,
{ type Item = (I::Item, J::Item);
fn size_hint(&self) -> (usize, Option<usize>) { // Not ExactSizeIterator because size may be larger than usize // Compute a * b_orig + b for both lower and upper bound letmut sh = size_hint::mul(self.a.size_hint(), self.b_orig.size_hint()); if matches!(self.a_cur, Some(Some(_))) {
sh = size_hint::add(sh, self.b.size_hint());
}
sh
}
fn fold<Acc, G>(self, mut accum: Acc, mut f: G) -> Acc where
G: FnMut(Acc, Self::Item) -> Acc,
{ // use a split loop to handle the loose a_cur as well as avoiding to // clone b_orig at the end. letSelf { mut a,
a_cur, mut b,
b_orig,
} = self; iflet Some(mut elt_a) = a_cur.unwrap_or_else(|| a.next()) { loop {
accum = b.fold(accum, |acc, elt| f(acc, (elt_a.clone(), elt)));
// we can only continue iterating a if we had a first element; iflet Some(next_elt_a) = a.next() {
b = b_orig.clone();
elt_a = next_elt_a;
} else { break;
}
}
}
accum
}
}
impl<I, J> FusedIterator for Product<I, J> where
I: FusedIterator,
J: Clone + FusedIterator,
I::Item: Clone,
{
}
/// A “meta iterator adaptor”. Its closure receives a reference to the iterator /// and may pick off as many elements as it likes, to produce the next iterator element. /// /// Iterator element type is `X` if the return type of `F` is `Option<X>`. /// /// See [`.batching()`](crate::Itertools::batching) for more information. #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct Batching<I, F> {
f: F,
iter: I,
}
impl<I, F> fmt::Debug for Batching<I, F> where
I: fmt::Debug,
{
debug_fmt_fields!(Batching, iter);
}
/// Create a new Batching iterator. pubfn batching<I, F>(iter: I, f: F) -> Batching<I, F> {
Batching { f, iter }
}
impl<B, F, I> Iterator for Batching<I, F> where
I: Iterator,
F: FnMut(&mut I) -> Option<B>,
{ type Item = B; #[inline] fn next(&mutself) -> Option<Self::Item> {
(self.f)(&mutself.iter)
}
}
/// An iterator adaptor that borrows from a `Clone`-able iterator /// to only pick off elements while the predicate returns `true`. /// /// See [`.take_while_ref()`](crate::Itertools::take_while_ref) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct TakeWhileRef<'a, I: 'a, F> {
iter: &'a mut I,
f: F,
}
impl<I, F> fmt::Debug for TakeWhileRef<'_, I, F> where
I: Iterator + fmt::Debug,
{
debug_fmt_fields!(TakeWhileRef, iter);
}
/// Create a new `TakeWhileRef` from a reference to clonable iterator. pubfn take_while_ref<I, F>(iter: &mut I, f: F) -> TakeWhileRef<I, F> where
I: Iterator + Clone,
{
TakeWhileRef { iter, f }
}
impl<I, F> Iterator for TakeWhileRef<'_, I, F> where
I: Iterator + Clone,
F: FnMut(&I::Item) -> bool,
{ type Item = I::Item;
/// An iterator adaptor that filters `Option<A>` iterator elements /// and produces `A`. Stops on the first `None` encountered. /// /// See [`.while_some()`](crate::Itertools::while_some) for more information. #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct WhileSome<I> {
iter: I,
}
/// Create a new `WhileSome<I>`. pubfn while_some<I>(iter: I) -> WhileSome<I> {
WhileSome { iter }
}
impl<I, A> Iterator for WhileSome<I> where
I: Iterator<Item = Option<A>>,
{ type Item = A;
fn fold<B, F>(mutself, acc: B, mut f: F) -> B where Self: Sized,
F: FnMut(B, Self::Item) -> B,
{ let res = self.iter.try_fold(acc, |acc, item| match item {
Some(item) => Ok(f(acc, item)),
None => Err(acc),
});
match res {
Ok(val) => val,
Err(val) => val,
}
}
}
/// An iterator to iterate through all combinations in a `Clone`-able iterator that produces tuples /// of a specific size. /// /// See [`.tuple_combinations()`](crate::Itertools::tuple_combinations) for more /// information. #[derive(Clone, Debug)] #[must_use = "this iterator adaptor is not lazy but does nearly nothing unless consumed"] pubstruct TupleCombinations<I, T> where
I: Iterator,
T: HasCombination<I>,
{
iter: T::Combination,
_mi: PhantomData<I>,
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B where
F: FnMut(B, Self::Item) -> B,
{ // We outline this closure to prevent it from unnecessarily // capturing the type parameters `I`, `B`, and `F`. Not doing // so ended up causing exponentially big types during MIR // inlining when building itertools with optimizations enabled. // // This change causes a small improvement to compile times in // release mode. type CurrTuple<A> = (A, $(ignore_ident!($X, A)),*); type PrevTuple<A> = ($(ignore_ident!($X, A),)*); fn map_fn<A: Clone>(z: &A) -> impl FnMut(PrevTuple<A>) -> CurrTuple<A> + '_ { move |($($X,)*)| (z.clone(), $($X),*)
} letSelf { c, item, mut iter } = self; iflet Some(z) = item.as_ref() {
init = c
.map(map_fn::<A>(z))
.fold(init, &mut f);
} whilelet Some(z) = iter.next() { let c: $P<I> = iter.clone().into();
init = c
.map(map_fn::<A>(&z))
.fold(init, &mut f);
}
init
}
}
impl<I, A> HasCombination<I> for (A, $(ignore_ident!($X, A)),*) where I: Iterator<Item = A> + Clone,
I::Item: Clone
{ type Combination = $C<Fuse<I>>;
}
)
}
// This snippet generates the twelve `impl_tuple_combination!` invocations: // use core::iter; // use itertools::Itertools; // // for i in 2..=12 { // println!("impl_tuple_combination!(Tuple{arity}Combination Tuple{prev}Combination; {idents});", // arity = i, // prev = i - 1, // idents = ('a'..'z').take(i - 1).join(" "), // ); // } // It could probably be replaced by a bit more macro cleverness.
impl_tuple_combination!(Tuple2Combination Tuple1Combination; a);
impl_tuple_combination!(Tuple3Combination Tuple2Combination; a b);
impl_tuple_combination!(Tuple4Combination Tuple3Combination; a b c);
impl_tuple_combination!(Tuple5Combination Tuple4Combination; a b c d);
impl_tuple_combination!(Tuple6Combination Tuple5Combination; a b c d e);
impl_tuple_combination!(Tuple7Combination Tuple6Combination; a b c d e f);
impl_tuple_combination!(Tuple8Combination Tuple7Combination; a b c d e f g);
impl_tuple_combination!(Tuple9Combination Tuple8Combination; a b c d e f g h);
impl_tuple_combination!(Tuple10Combination Tuple9Combination; a b c d e f g h i);
impl_tuple_combination!(Tuple11Combination Tuple10Combination; a b c d e f g h i j);
impl_tuple_combination!(Tuple12Combination Tuple11Combination; a b c d e f g h i j k);
// https://en.wikipedia.org/wiki/Binomial_coefficient#In_programming_languages pub(crate) fn checked_binomial(mut n: usize, mut k: usize) -> Option<usize> { if n < k { return Some(0);
} // `factorial(n) / factorial(n - k) / factorial(k)` but trying to avoid it overflows:
k = (n - k).min(k); // symmetry letmut c = 1; for i in1..=k {
c = (c / i)
.checked_mul(n)?
.checked_add((c % i).checked_mul(n)? / i)?;
n -= 1;
}
Some(c)
}
#[test] fn test_checked_binomial() { // With the first row: [1, 0, 0, ...] and the first column full of 1s, we check // row by row the recurrence relation of binomials (which is an equivalent definition). // For n >= 1 and k >= 1 we have: // binomial(n, k) == binomial(n - 1, k - 1) + binomial(n - 1, k) const LIMIT: usize = 500; letmut row = vec![Some(0); LIMIT + 1];
row[0] = Some(1); for n in0..=LIMIT { for k in0..=LIMIT {
assert_eq!(row[k], checked_binomial(n, k));
}
row = std::iter::once(Some(1))
.chain((1..=LIMIT).map(|k| row[k - 1]?.checked_add(row[k]?)))
.collect();
}
}
/// An iterator adapter to filter values within a nested `Result::Ok`. /// /// See [`.filter_ok()`](crate::Itertools::filter_ok) for more information. #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct FilterOk<I, F> {
iter: I,
f: F,
}
impl<I, F> fmt::Debug for FilterOk<I, F> where
I: fmt::Debug,
{
debug_fmt_fields!(FilterOk, iter);
}
/// Create a new `FilterOk` iterator. pubfn filter_ok<I, F, T, E>(iter: I, f: F) -> FilterOk<I, F> where
I: Iterator<Item = Result<T, E>>,
F: FnMut(&T) -> bool,
{
FilterOk { iter, f }
}
impl<I, F, T, E> Iterator for FilterOk<I, F> where
I: Iterator<Item = Result<T, E>>,
F: FnMut(&T) -> bool,
{ type Item = Result<T, E>;
fn next(&mutself) -> Option<Self::Item> { let f = &mutself.f; self.iter.find(|res| match res {
Ok(t) => f(t),
_ => true,
})
}
impl<I, F, T, E> FusedIterator for FilterOk<I, F> where
I: FusedIterator<Item = Result<T, E>>,
F: FnMut(&T) -> bool,
{
}
/// An iterator adapter to filter and apply a transformation on values within a nested `Result::Ok`. /// /// See [`.filter_map_ok()`](crate::Itertools::filter_map_ok) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Clone)] pubstruct FilterMapOk<I, F> {
iter: I,
f: F,
}
impl<I, F> fmt::Debug for FilterMapOk<I, F> where
I: fmt::Debug,
{
debug_fmt_fields!(FilterMapOk, iter);
}
impl<I, F, T, U, E> FusedIterator for FilterMapOk<I, F> where
I: FusedIterator<Item = Result<T, E>>,
F: FnMut(T) -> Option<U>,
{
}
/// An iterator adapter to get the positions of each element that matches a predicate. /// /// See [`.positions()`](crate::Itertools::positions) for more information. #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct Positions<I, F> {
iter: Enumerate<I>,
f: F,
}
impl<I, F> fmt::Debug for Positions<I, F> where
I: fmt::Debug,
{
debug_fmt_fields!(Positions, iter);
}
/// Create a new `Positions` iterator. pubfn positions<I, F>(iter: I, f: F) -> Positions<I, F> where
I: Iterator,
F: FnMut(I::Item) -> bool,
{ let iter = iter.enumerate();
Positions { iter, f }
}
impl<I, F> Iterator for Positions<I, F> where
I: Iterator,
F: FnMut(I::Item) -> bool,
{ type Item = usize;
fn next(&mutself) -> Option<Self::Item> { let f = &mutself.f; self.iter.find_map(|(count, val)| f(val).then_some(count))
}
fn fold<B, G>(self, init: B, mut func: G) -> B where
G: FnMut(B, Self::Item) -> B,
{ letmut f = self.f; self.iter.fold(init, |mut acc, (count, val)| { if f(val) {
acc = func(acc, count);
}
acc
})
}
}
impl<I, F> DoubleEndedIterator for Positions<I, F> where
I: DoubleEndedIterator + ExactSizeIterator,
F: FnMut(I::Item) -> bool,
{ fn next_back(&mutself) -> Option<Self::Item> { let f = &mutself.f; self.iter
.by_ref()
.rev()
.find_map(|(count, val)| f(val).then_some(count))
}
fn rfold<B, G>(self, init: B, mut func: G) -> B where
G: FnMut(B, Self::Item) -> B,
{ letmut f = self.f; self.iter.rfold(init, |mut acc, (count, val)| { if f(val) {
acc = func(acc, count);
}
acc
})
}
}
impl<I, F> FusedIterator for Positions<I, F> where
I: FusedIterator,
F: FnMut(I::Item) -> bool,
{
}
/// An iterator adapter to apply a mutating function to each element before yielding it. /// /// See [`.update()`](crate::Itertools::update) for more information. #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pubstruct Update<I, F> {
iter: I,
f: F,
}
impl<I, F> fmt::Debug for Update<I, F> where
I: fmt::Debug,
{
debug_fmt_fields!(Update, iter);
}
/// Create a new `Update` iterator. pubfn update<I, F>(iter: I, f: F) -> Update<I, F> where
I: Iterator,
F: FnMut(&mut I::Item),
{
Update { iter, f }
}
impl<I, F> Iterator for Update<I, F> where
I: Iterator,
F: FnMut(&mut I::Item),
{ type Item = I::Item;
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.