pub trait Itertools: Iterator {
Show 121 methods
// Provided methods
fn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter> ⓘ
where J: IntoIterator<Item = Self::Item>,
Self: Sized { ... }
fn interleave_shortest<J>(
self,
other: J,
) -> InterleaveShortest<Self, J::IntoIter> ⓘ
where J: IntoIterator<Item = Self::Item>,
Self: Sized { ... }
fn intersperse(self, element: Self::Item) -> Intersperse<Self>
where Self: Sized,
Self::Item: Clone { ... }
fn intersperse_with<F>(self, element: F) -> IntersperseWith<Self, F> ⓘ
where Self: Sized,
F: FnMut() -> Self::Item { ... }
fn get<R>(self, index: R) -> R::Output
where Self: Sized,
R: IteratorIndex<Self> { ... }
fn zip_longest<J>(self, other: J) -> ZipLongest<Self, J::IntoIter> ⓘ
where J: IntoIterator,
Self: Sized { ... }
fn zip_eq<J>(self, other: J) -> ZipEq<Self, J::IntoIter> ⓘ
where J: IntoIterator,
Self: Sized { ... }
fn batching<B, F>(self, f: F) -> Batching<Self, F> ⓘ
where F: FnMut(&mut Self) -> Option<B>,
Self: Sized { ... }
fn chunk_by<K, F>(self, key: F) -> ChunkBy<K, Self, F>
where Self: Sized,
F: FnMut(&Self::Item) -> K,
K: PartialEq { ... }
fn group_by<K, F>(self, key: F) -> ChunkBy<K, Self, F>
where Self: Sized,
F: FnMut(&Self::Item) -> K,
K: PartialEq { ... }
fn chunks(self, size: usize) -> IntoChunks<Self>
where Self: Sized { ... }
fn tuple_windows<T>(self) -> TupleWindows<Self, T> ⓘ
where Self: Sized + Iterator<Item = T::Item>,
T: HomogeneousTuple,
T::Item: Clone { ... }
fn circular_tuple_windows<T>(self) -> CircularTupleWindows<Self, T> ⓘ
where Self: Sized + Clone + Iterator<Item = T::Item> + ExactSizeIterator,
T: TupleCollect + Clone,
T::Item: Clone { ... }
fn tuples<T>(self) -> Tuples<Self, T> ⓘ
where Self: Sized + Iterator<Item = T::Item>,
T: HomogeneousTuple { ... }
fn tee(self) -> (Tee<Self>, Tee<Self>)
where Self: Sized,
Self::Item: Clone { ... }
fn map_into<R>(self) -> MapInto<Self, R>
where Self: Sized,
Self::Item: Into<R> { ... }
fn map_ok<F, T, U, E>(self, f: F) -> MapOk<Self, F>
where Self: Iterator<Item = Result<T, E>> + Sized,
F: FnMut(T) -> U { ... }
fn filter_ok<F, T, E>(self, f: F) -> FilterOk<Self, F> ⓘ
where Self: Iterator<Item = Result<T, E>> + Sized,
F: FnMut(&T) -> bool { ... }
fn filter_map_ok<F, T, U, E>(self, f: F) -> FilterMapOk<Self, F> ⓘ
where Self: Iterator<Item = Result<T, E>> + Sized,
F: FnMut(T) -> Option<U> { ... }
fn flatten_ok<T, E>(self) -> FlattenOk<Self, T, E> ⓘ
where Self: Iterator<Item = Result<T, E>> + Sized,
T: IntoIterator { ... }
fn process_results<F, T, E, R>(self, processor: F) -> Result<R, E>
where Self: Iterator<Item = Result<T, E>> + Sized,
F: FnOnce(ProcessResults<'_, Self, E>) -> R { ... }
fn merge<J>(self, other: J) -> Merge<Self, J::IntoIter>
where Self: Sized,
Self::Item: PartialOrd,
J: IntoIterator<Item = Self::Item> { ... }
fn merge_by<J, F>(
self,
other: J,
is_first: F,
) -> MergeBy<Self, J::IntoIter, F> ⓘ
where Self: Sized,
J: IntoIterator<Item = Self::Item>,
F: FnMut(&Self::Item, &Self::Item) -> bool { ... }
fn merge_join_by<J, F, T>(
self,
other: J,
cmp_fn: F,
) -> MergeJoinBy<Self, J::IntoIter, F>
where J: IntoIterator,
F: FnMut(&Self::Item, &J::Item) -> T,
Self: Sized { ... }
fn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter>
where Self: Sized,
Self::Item: IntoIterator,
<Self::Item as IntoIterator>::Item: PartialOrd { ... }
fn kmerge_by<F>(
self,
first: F,
) -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F> ⓘ
where Self: Sized,
Self::Item: IntoIterator,
F: FnMut(&<Self::Item as IntoIterator>::Item, &<Self::Item as IntoIterator>::Item) -> bool { ... }
fn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoIter> ⓘ
where Self: Sized,
Self::Item: Clone,
J: IntoIterator,
J::IntoIter: Clone { ... }
fn multi_cartesian_product(
self,
) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter> ⓘ
where Self: Sized,
Self::Item: IntoIterator,
<Self::Item as IntoIterator>::IntoIter: Clone,
<Self::Item as IntoIterator>::Item: Clone { ... }
fn coalesce<F>(self, f: F) -> Coalesce<Self, F>
where Self: Sized,
F: FnMut(Self::Item, Self::Item) -> Result<Self::Item, (Self::Item, Self::Item)> { ... }
fn dedup(self) -> Dedup<Self>
where Self: Sized,
Self::Item: PartialEq { ... }
fn dedup_by<Cmp>(self, cmp: Cmp) -> DedupBy<Self, Cmp>
where Self: Sized,
Cmp: FnMut(&Self::Item, &Self::Item) -> bool { ... }
fn dedup_with_count(self) -> DedupWithCount<Self>
where Self: Sized { ... }
fn dedup_by_with_count<Cmp>(self, cmp: Cmp) -> DedupByWithCount<Self, Cmp>
where Self: Sized,
Cmp: FnMut(&Self::Item, &Self::Item) -> bool { ... }
fn duplicates(self) -> Duplicates<Self>
where Self: Sized,
Self::Item: Eq + Hash { ... }
fn duplicates_by<V, F>(self, f: F) -> DuplicatesBy<Self, V, F>
where Self: Sized,
V: Eq + Hash,
F: FnMut(&Self::Item) -> V { ... }
fn unique(self) -> Unique<Self> ⓘ
where Self: Sized,
Self::Item: Clone + Eq + Hash { ... }
fn unique_by<V, F>(self, f: F) -> UniqueBy<Self, V, F> ⓘ
where Self: Sized,
V: Eq + Hash,
F: FnMut(&Self::Item) -> V { ... }
fn peeking_take_while<F>(
&mut self,
accept: F,
) -> PeekingTakeWhile<'_, Self, F> ⓘ
where Self: Sized + PeekingNext,
F: FnMut(&Self::Item) -> bool { ... }
fn take_while_ref<F>(&mut self, accept: F) -> TakeWhileRef<'_, Self, F> ⓘ
where Self: Clone,
F: FnMut(&Self::Item) -> bool { ... }
fn take_while_inclusive<F>(self, accept: F) -> TakeWhileInclusive<Self, F> ⓘ
where Self: Sized,
F: FnMut(&Self::Item) -> bool { ... }
fn while_some<A>(self) -> WhileSome<Self> ⓘ
where Self: Sized + Iterator<Item = Option<A>> { ... }
fn tuple_combinations<T>(self) -> TupleCombinations<Self, T> ⓘ
where Self: Sized + Clone,
Self::Item: Clone,
T: HasCombination<Self> { ... }
fn combinations(self, k: usize) -> Combinations<Self> ⓘ
where Self: Sized,
Self::Item: Clone { ... }
fn combinations_with_replacement(
self,
k: usize,
) -> CombinationsWithReplacement<Self> ⓘ
where Self: Sized,
Self::Item: Clone { ... }
fn permutations(self, k: usize) -> Permutations<Self> ⓘ
where Self: Sized,
Self::Item: Clone { ... }
fn powerset(self) -> Powerset<Self> ⓘ
where Self: Sized,
Self::Item: Clone { ... }
fn pad_using<F>(self, min: usize, f: F) -> PadUsing<Self, F> ⓘ
where Self: Sized,
F: FnMut(usize) -> Self::Item { ... }
fn with_position(self) -> WithPosition<Self> ⓘ
where Self: Sized { ... }
fn positions<P>(self, predicate: P) -> Positions<Self, P> ⓘ
where Self: Sized,
P: FnMut(Self::Item) -> bool { ... }
fn update<F>(self, updater: F) -> Update<Self, F> ⓘ
where Self: Sized,
F: FnMut(&mut Self::Item) { ... }
fn next_tuple<T>(&mut self) -> Option<T>
where Self: Sized + Iterator<Item = T::Item>,
T: HomogeneousTuple { ... }
fn collect_tuple<T>(self) -> Option<T>
where Self: Sized + Iterator<Item = T::Item>,
T: HomogeneousTuple { ... }
fn find_position<P>(&mut self, pred: P) -> Option<(usize, Self::Item)>
where P: FnMut(&Self::Item) -> bool { ... }
fn find_or_last<P>(self, predicate: P) -> Option<Self::Item>
where Self: Sized,
P: FnMut(&Self::Item) -> bool { ... }
fn find_or_first<P>(self, predicate: P) -> Option<Self::Item>
where Self: Sized,
P: FnMut(&Self::Item) -> bool { ... }
fn contains<Q>(&mut self, query: &Q) -> bool
where Self: Sized,
Self::Item: Borrow<Q>,
Q: PartialEq { ... }
fn all_equal(&mut self) -> bool
where Self: Sized,
Self::Item: PartialEq { ... }
fn all_equal_value(
&mut self,
) -> Result<Self::Item, Option<(Self::Item, Self::Item)>>
where Self: Sized,
Self::Item: PartialEq { ... }
fn all_unique(&mut self) -> bool
where Self: Sized,
Self::Item: Eq + Hash { ... }
fn dropping(self, n: usize) -> Self
where Self: Sized { ... }
fn dropping_back(self, n: usize) -> Self
where Self: Sized + DoubleEndedIterator { ... }
fn concat(self) -> Self::Item
where Self: Sized,
Self::Item: Extend<<<Self as Iterator>::Item as IntoIterator>::Item> + IntoIterator + Default { ... }
fn collect_vec(self) -> Vec<Self::Item>
where Self: Sized { ... }
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>> { ... }
fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize
where Self: Iterator<Item = &'a mut A>,
J: IntoIterator<Item = A> { ... }
fn join(&mut self, sep: &str) -> String
where Self::Item: Display { ... }
fn format(self, sep: &str) -> Format<'_, Self>
where Self: Sized { ... }
fn format_with<F>(self, sep: &str, format: F) -> FormatWith<'_, Self, F>
where Self: Sized,
F: FnMut(Self::Item, &mut dyn FnMut(&dyn Display) -> Result) -> Result { ... }
fn fold_ok<A, E, B, F>(&mut self, start: B, f: F) -> Result<B, E>
where Self: Iterator<Item = Result<A, E>>,
F: FnMut(B, A) -> B { ... }
fn fold_options<A, B, F>(&mut self, start: B, f: F) -> Option<B>
where Self: Iterator<Item = Option<A>>,
F: FnMut(B, A) -> B { ... }
fn fold1<F>(self, f: F) -> Option<Self::Item>
where F: FnMut(Self::Item, Self::Item) -> Self::Item,
Self: Sized { ... }
fn tree_reduce<F>(self, f: F) -> Option<Self::Item>
where F: FnMut(Self::Item, Self::Item) -> Self::Item,
Self: Sized { ... }
fn tree_fold1<F>(self, f: F) -> Option<Self::Item>
where F: FnMut(Self::Item, Self::Item) -> Self::Item,
Self: Sized { ... }
fn fold_while<B, F>(&mut self, init: B, f: F) -> FoldWhile<B>
where Self: Sized,
F: FnMut(B, Self::Item) -> FoldWhile<B> { ... }
fn sum1<S>(self) -> Option<S>
where Self: Sized,
S: Sum<Self::Item> { ... }
fn product1<P>(self) -> Option<P>
where Self: Sized,
P: Product<Self::Item> { ... }
fn sorted_unstable(self) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
Self::Item: Ord { ... }
fn sorted_unstable_by<F>(self, cmp: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn sorted_unstable_by_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
K: Ord,
F: FnMut(&Self::Item) -> K { ... }
fn sorted(self) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
Self::Item: Ord { ... }
fn sorted_by<F>(self, cmp: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn sorted_by_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
K: Ord,
F: FnMut(&Self::Item) -> K { ... }
fn sorted_by_cached_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
K: Ord,
F: FnMut(&Self::Item) -> K { ... }
fn k_smallest(self, k: usize) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
Self::Item: Ord { ... }
fn k_smallest_by<F>(self, k: usize, cmp: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn k_smallest_by_key<F, K>(self, k: usize, key: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
F: FnMut(&Self::Item) -> K,
K: Ord { ... }
fn k_largest(self, k: usize) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
Self::Item: Ord { ... }
fn k_largest_by<F>(self, k: usize, cmp: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn k_largest_by_key<F, K>(self, k: usize, key: F) -> IntoIter<Self::Item> ⓘ
where Self: Sized,
F: FnMut(&Self::Item) -> K,
K: Ord { ... }
fn tail(self, n: usize) -> IntoIter<Self::Item> ⓘ
where Self: Sized { ... }
fn partition_map<A, B, F, L, R>(self, predicate: F) -> (A, B)
where Self: Sized,
F: FnMut(Self::Item) -> Either<L, R>,
A: Default + Extend<L>,
B: Default + Extend<R> { ... }
fn partition_result<A, B, T, E>(self) -> (A, B)
where Self: Iterator<Item = Result<T, E>> + Sized,
A: Default + Extend<T>,
B: Default + Extend<E> { ... }
fn into_group_map<K, V>(self) -> HashMap<K, Vec<V>>
where Self: Iterator<Item = (K, V)> + Sized,
K: Hash + Eq { ... }
fn into_group_map_by<K, V, F>(self, f: F) -> HashMap<K, Vec<V>>
where Self: Iterator<Item = V> + Sized,
K: Hash + Eq,
F: FnMut(&V) -> K { ... }
fn into_grouping_map<K, V>(self) -> GroupingMap<Self>
where Self: Iterator<Item = (K, V)> + Sized,
K: Hash + Eq { ... }
fn into_grouping_map_by<K, V, F>(
self,
key_mapper: F,
) -> GroupingMapBy<Self, F>
where Self: Iterator<Item = V> + Sized,
K: Hash + Eq,
F: FnMut(&V) -> K { ... }
fn min_set(self) -> Vec<Self::Item>
where Self: Sized,
Self::Item: Ord { ... }
fn min_set_by<F>(self, compare: F) -> Vec<Self::Item>
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn min_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
where Self: Sized,
K: Ord,
F: FnMut(&Self::Item) -> K { ... }
fn max_set(self) -> Vec<Self::Item>
where Self: Sized,
Self::Item: Ord { ... }
fn max_set_by<F>(self, compare: F) -> Vec<Self::Item>
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn max_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
where Self: Sized,
K: Ord,
F: FnMut(&Self::Item) -> K { ... }
fn minmax(self) -> MinMaxResult<Self::Item>
where Self: Sized,
Self::Item: PartialOrd { ... }
fn minmax_by_key<K, F>(self, key: F) -> MinMaxResult<Self::Item>
where Self: Sized,
K: PartialOrd,
F: FnMut(&Self::Item) -> K { ... }
fn minmax_by<F>(self, compare: F) -> MinMaxResult<Self::Item>
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn position_max(self) -> Option<usize>
where Self: Sized,
Self::Item: Ord { ... }
fn position_max_by_key<K, F>(self, key: F) -> Option<usize>
where Self: Sized,
K: Ord,
F: FnMut(&Self::Item) -> K { ... }
fn position_max_by<F>(self, compare: F) -> Option<usize>
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn position_min(self) -> Option<usize>
where Self: Sized,
Self::Item: Ord { ... }
fn position_min_by_key<K, F>(self, key: F) -> Option<usize>
where Self: Sized,
K: Ord,
F: FnMut(&Self::Item) -> K { ... }
fn position_min_by<F>(self, compare: F) -> Option<usize>
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn position_minmax(self) -> MinMaxResult<usize>
where Self: Sized,
Self::Item: PartialOrd { ... }
fn position_minmax_by_key<K, F>(self, key: F) -> MinMaxResult<usize>
where Self: Sized,
K: PartialOrd,
F: FnMut(&Self::Item) -> K { ... }
fn position_minmax_by<F>(self, compare: F) -> MinMaxResult<usize>
where Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }
fn exactly_one(self) -> Result<Self::Item, ExactlyOneError<Self>>
where Self: Sized { ... }
fn at_most_one(self) -> Result<Option<Self::Item>, ExactlyOneError<Self>>
where Self: Sized { ... }
fn multipeek(self) -> MultiPeek<Self> ⓘ
where Self: Sized { ... }
fn counts(self) -> HashMap<Self::Item, usize>
where Self: Sized,
Self::Item: Eq + Hash { ... }
fn counts_by<K, F>(self, f: F) -> HashMap<K, usize>
where Self: Sized,
K: Eq + Hash,
F: FnMut(Self::Item) -> K { ... }
fn multiunzip<FromI>(self) -> FromI
where Self: Sized + MultiUnzip<FromI> { ... }
fn try_len(&self) -> Result<usize, (usize, Option<usize>)> { ... }
}
Expand description
An Iterator
blanket implementation that provides extra adaptors and
methods.
This trait defines a number of methods. They are divided into two groups:
-
Adaptors take an iterator and parameter as input, and return a new iterator value. These are listed first in the trait. An example of an adaptor is
.interleave()
-
Regular methods are those that don’t return iterators and instead return a regular value of some other kind.
.next_tuple()
is an example and the first regular method in the list.
Provided Methods§
sourcefn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter> ⓘ
fn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter> ⓘ
Alternate elements from two iterators until both have run out.
Iterator element type is Self::Item
.
This iterator is fused.
use itertools::Itertools;
let it = (1..7).interleave(vec![-1, -2]);
itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]);
sourcefn interleave_shortest<J>(
self,
other: J,
) -> InterleaveShortest<Self, J::IntoIter> ⓘ
fn interleave_shortest<J>( self, other: J, ) -> InterleaveShortest<Self, J::IntoIter> ⓘ
Alternate elements from two iterators until at least one of them has run out.
Iterator element type is Self::Item
.
use itertools::Itertools;
let it = (1..7).interleave_shortest(vec![-1, -2]);
itertools::assert_equal(it, vec![1, -1, 2, -2, 3]);
sourcefn intersperse(self, element: Self::Item) -> Intersperse<Self>
fn intersperse(self, element: Self::Item) -> Intersperse<Self>
An iterator adaptor to insert a particular value between each element of the adapted iterator.
Iterator element type is Self::Item
.
This iterator is fused.
use itertools::Itertools;
itertools::assert_equal((0..3).intersperse(8), vec![0, 8, 1, 8, 2]);
sourcefn intersperse_with<F>(self, element: F) -> IntersperseWith<Self, F> ⓘ
fn intersperse_with<F>(self, element: F) -> IntersperseWith<Self, F> ⓘ
An iterator adaptor to insert a particular value created by a function between each element of the adapted iterator.
Iterator element type is Self::Item
.
This iterator is fused.
use itertools::Itertools;
let mut i = 10;
itertools::assert_equal((0..3).intersperse_with(|| { i -= 1; i }), vec![0, 9, 1, 8, 2]);
assert_eq!(i, 8);
sourcefn get<R>(self, index: R) -> R::Outputwhere
Self: Sized,
R: IteratorIndex<Self>,
fn get<R>(self, index: R) -> R::Outputwhere
Self: Sized,
R: IteratorIndex<Self>,
Returns an iterator over a subsection of the iterator.
Works similarly to slice::get
.
Panics for ranges ..=usize::MAX
and 0..=usize::MAX
.
It’s a generalisation of Iterator::take
and Iterator::skip
,
and uses these under the hood.
Therefore, the resulting iterator is:
ExactSizeIterator
if the adapted iterator isExactSizeIterator
.DoubleEndedIterator
if the adapted iterator isDoubleEndedIterator
andExactSizeIterator
.
§Unspecified Behavior
The result of indexing with an exhausted core::ops::RangeInclusive
is unspecified.
§Examples
use itertools::Itertools;
let vec = vec![3, 1, 4, 1, 5];
let mut range: Vec<_> =
vec.iter().get(1..=3).copied().collect();
assert_eq!(&range, &[1, 4, 1]);
// It works with other types of ranges, too
range = vec.iter().get(..2).copied().collect();
assert_eq!(&range, &[3, 1]);
range = vec.iter().get(0..1).copied().collect();
assert_eq!(&range, &[3]);
range = vec.iter().get(2..).copied().collect();
assert_eq!(&range, &[4, 1, 5]);
range = vec.iter().get(..=2).copied().collect();
assert_eq!(&range, &[3, 1, 4]);
range = vec.iter().get(..).copied().collect();
assert_eq!(range, vec);
sourcefn zip_longest<J>(self, other: J) -> ZipLongest<Self, J::IntoIter> ⓘwhere
J: IntoIterator,
Self: Sized,
fn zip_longest<J>(self, other: J) -> ZipLongest<Self, J::IntoIter> ⓘwhere
J: IntoIterator,
Self: Sized,
Create an iterator which iterates over both this and the specified iterator simultaneously, yielding pairs of two optional elements.
This iterator is fused.
As long as neither input iterator is exhausted yet, it yields two values
via EitherOrBoth::Both
.
When the parameter iterator is exhausted, it only yields a value from the
self
iterator via EitherOrBoth::Left
.
When the self
iterator is exhausted, it only yields a value from the
parameter iterator via EitherOrBoth::Right
.
When both iterators return None
, all further invocations of .next()
will return None
.
Iterator element type is
EitherOrBoth<Self::Item, J::Item>
.
use itertools::EitherOrBoth::{Both, Right};
use itertools::Itertools;
let it = (0..1).zip_longest(1..3);
itertools::assert_equal(it, vec![Both(0, 1), Right(2)]);
sourcefn zip_eq<J>(self, other: J) -> ZipEq<Self, J::IntoIter> ⓘwhere
J: IntoIterator,
Self: Sized,
fn zip_eq<J>(self, other: J) -> ZipEq<Self, J::IntoIter> ⓘwhere
J: IntoIterator,
Self: Sized,
Create an iterator which iterates over both this and the specified iterator simultaneously, yielding pairs of elements.
Panics if the iterators reach an end and they are not of equal lengths.
sourcefn batching<B, F>(self, f: F) -> Batching<Self, F> ⓘ
fn batching<B, F>(self, f: F) -> Batching<Self, F> ⓘ
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 B
.
use itertools::Itertools;
// An adaptor that gathers elements in pairs
let pit = (0..4).batching(|it| {
match it.next() {
None => None,
Some(x) => match it.next() {
None => None,
Some(y) => Some((x, y)),
}
}
});
itertools::assert_equal(pit, vec![(0, 1), (2, 3)]);
sourcefn chunk_by<K, F>(self, key: F) -> ChunkBy<K, Self, F>
fn chunk_by<K, F>(self, key: F) -> ChunkBy<K, Self, F>
Return an iterable that can group iterator elements. Consecutive elements that map to the same key (“runs”), are assigned to the same group.
ChunkBy
is the storage for the lazy grouping operation.
If the groups are consumed in order, or if each group’s iterator is
dropped without keeping it around, then ChunkBy
uses no
allocations. It needs allocations only if several group iterators
are alive at the same time.
This type implements IntoIterator
(it is not an iterator
itself), because the group iterators need to borrow from this
value. It should be stored in a local variable or temporary and
iterated.
Iterator element type is (K, Group)
: the group’s key and the
group iterator.
use itertools::Itertools;
// chunk data into runs of larger than zero or not.
let data = vec![1, 3, -2, -2, 1, 0, 1, 2];
// chunks: |---->|------>|--------->|
// Note: The `&` is significant here, `ChunkBy` is iterable
// only by reference. You can also call `.into_iter()` explicitly.
let mut data_grouped = Vec::new();
for (key, chunk) in &data.into_iter().chunk_by(|elt| *elt >= 0) {
data_grouped.push((key, chunk.collect()));
}
assert_eq!(data_grouped, vec![(true, vec![1, 3]), (false, vec![-2, -2]), (true, vec![1, 0, 1, 2])]);
sourcefn group_by<K, F>(self, key: F) -> ChunkBy<K, Self, F>
👎Deprecated since 0.13.0: Use .chunk_by() instead
fn group_by<K, F>(self, key: F) -> ChunkBy<K, Self, F>
See .chunk_by()
.
sourcefn chunks(self, size: usize) -> IntoChunks<Self>where
Self: Sized,
fn chunks(self, size: usize) -> IntoChunks<Self>where
Self: Sized,
Return an iterable that can chunk the iterator.
Yield subiterators (chunks) that each yield a fixed number elements,
determined by size
. The last chunk will be shorter if there aren’t
enough elements.
IntoChunks
is based on ChunkBy
: it is iterable (implements
IntoIterator
, not Iterator
), and it only buffers if several
chunk iterators are alive at the same time.
Iterator element type is Chunk
, each chunk’s iterator.
Panics if size
is 0.
use itertools::Itertools;
let data = vec![1, 1, 2, -2, 6, 0, 3, 1];
//chunk size=3 |------->|-------->|--->|
// Note: The `&` is significant here, `IntoChunks` is iterable
// only by reference. You can also call `.into_iter()` explicitly.
for chunk in &data.into_iter().chunks(3) {
// Check that the sum of each chunk is 4.
assert_eq!(4, chunk.sum());
}
sourcefn tuple_windows<T>(self) -> TupleWindows<Self, T> ⓘ
fn tuple_windows<T>(self) -> TupleWindows<Self, T> ⓘ
Return an iterator over all contiguous windows producing tuples of a specific size (up to 12).
tuple_windows
clones the iterator elements so that they can be
part of successive windows, this makes it most suited for iterators
of references and other values that are cheap to copy.
use itertools::Itertools;
let mut v = Vec::new();
// pairwise iteration
for (a, b) in (1..5).tuple_windows() {
v.push((a, b));
}
assert_eq!(v, vec![(1, 2), (2, 3), (3, 4)]);
let mut it = (1..5).tuple_windows();
assert_eq!(Some((1, 2, 3)), it.next());
assert_eq!(Some((2, 3, 4)), it.next());
assert_eq!(None, it.next());
// this requires a type hint
let it = (1..5).tuple_windows::<(_, _, _)>();
itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]);
// you can also specify the complete type
use itertools::TupleWindows;
use std::ops::Range;
let it: TupleWindows<Range<u32>, (u32, u32, u32)> = (1..5).tuple_windows();
itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]);
sourcefn circular_tuple_windows<T>(self) -> CircularTupleWindows<Self, T> ⓘwhere
Self: Sized + Clone + Iterator<Item = T::Item> + ExactSizeIterator,
T: TupleCollect + Clone,
T::Item: Clone,
fn circular_tuple_windows<T>(self) -> CircularTupleWindows<Self, T> ⓘwhere
Self: Sized + Clone + Iterator<Item = T::Item> + ExactSizeIterator,
T: TupleCollect + Clone,
T::Item: Clone,
Return 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 (up to 12).
circular_tuple_windows
clones the iterator elements so that they can be
part of successive windows, this makes it most suited for iterators
of references and other values that are cheap to copy.
use itertools::Itertools;
let mut v = Vec::new();
for (a, b) in (1..5).circular_tuple_windows() {
v.push((a, b));
}
assert_eq!(v, vec![(1, 2), (2, 3), (3, 4), (4, 1)]);
let mut it = (1..5).circular_tuple_windows();
assert_eq!(Some((1, 2, 3)), it.next());
assert_eq!(Some((2, 3, 4)), it.next());
assert_eq!(Some((3, 4, 1)), it.next());
assert_eq!(Some((4, 1, 2)), it.next());
assert_eq!(None, it.next());
// this requires a type hint
let it = (1..5).circular_tuple_windows::<(_, _, _)>();
itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4), (3, 4, 1), (4, 1, 2)]);
sourcefn tuples<T>(self) -> Tuples<Self, T> ⓘ
fn tuples<T>(self) -> Tuples<Self, T> ⓘ
Return an iterator that groups the items in tuples of a specific size (up to 12).
See also the method .next_tuple()
.
use itertools::Itertools;
let mut v = Vec::new();
for (a, b) in (1..5).tuples() {
v.push((a, b));
}
assert_eq!(v, vec![(1, 2), (3, 4)]);
let mut it = (1..7).tuples();
assert_eq!(Some((1, 2, 3)), it.next());
assert_eq!(Some((4, 5, 6)), it.next());
assert_eq!(None, it.next());
// this requires a type hint
let it = (1..7).tuples::<(_, _, _)>();
itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]);
// you can also specify the complete type
use itertools::Tuples;
use std::ops::Range;
let it: Tuples<Range<u32>, (u32, u32, u32)> = (1..7).tuples();
itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]);
See also Tuples::into_buffer
.
sourcefn tee(self) -> (Tee<Self>, Tee<Self>)
fn tee(self) -> (Tee<Self>, Tee<Self>)
Split into an iterator pair that both yield all elements from the original iterator.
Note: If the iterator is clonable, prefer using that instead of using this method. Cloning is likely to be more efficient.
Iterator element type is Self::Item
.
use itertools::Itertools;
let xs = vec![0, 1, 2, 3];
let (mut t1, t2) = xs.into_iter().tee();
itertools::assert_equal(t1.next(), Some(0));
itertools::assert_equal(t2, 0..4);
itertools::assert_equal(t1, 1..4);
sourcefn map_into<R>(self) -> MapInto<Self, R>
fn map_into<R>(self) -> MapInto<Self, R>
Convert each item of the iterator using the Into
trait.
use itertools::Itertools;
(1i32..42i32).map_into::<f64>().collect_vec();
sourcefn map_ok<F, T, U, E>(self, f: F) -> MapOk<Self, F>
fn map_ok<F, T, U, E>(self, f: F) -> MapOk<Self, F>
Return an iterator adaptor that applies the provided closure
to every Result::Ok
value. Result::Err
values are
unchanged.
use itertools::Itertools;
let input = vec![Ok(41), Err(false), Ok(11)];
let it = input.into_iter().map_ok(|i| i + 1);
itertools::assert_equal(it, vec![Ok(42), Err(false), Ok(12)]);
sourcefn filter_ok<F, T, E>(self, f: F) -> FilterOk<Self, F> ⓘ
fn filter_ok<F, T, E>(self, f: F) -> FilterOk<Self, F> ⓘ
Return an iterator adaptor that filters every Result::Ok
value with the provided closure. Result::Err
values are
unchanged.
use itertools::Itertools;
let input = vec![Ok(22), Err(false), Ok(11)];
let it = input.into_iter().filter_ok(|&i| i > 20);
itertools::assert_equal(it, vec![Ok(22), Err(false)]);
sourcefn filter_map_ok<F, T, U, E>(self, f: F) -> FilterMapOk<Self, F> ⓘ
fn filter_map_ok<F, T, U, E>(self, f: F) -> FilterMapOk<Self, F> ⓘ
Return an iterator adaptor that filters and transforms every
Result::Ok
value with the provided closure. Result::Err
values are unchanged.
use itertools::Itertools;
let input = vec![Ok(22), Err(false), Ok(11)];
let it = input.into_iter().filter_map_ok(|i| if i > 20 { Some(i * 2) } else { None });
itertools::assert_equal(it, vec![Ok(44), Err(false)]);
sourcefn flatten_ok<T, E>(self) -> FlattenOk<Self, T, E> ⓘ
fn flatten_ok<T, E>(self) -> FlattenOk<Self, T, E> ⓘ
Return an iterator adaptor that flattens every Result::Ok
value into
a series of Result::Ok
values. Result::Err
values are unchanged.
This is useful when you have some common error type for your crate and
need to propagate it upwards, but the Result::Ok
case needs to be flattened.
use itertools::Itertools;
let input = vec![Ok(0..2), Err(false), Ok(2..4)];
let it = input.iter().cloned().flatten_ok();
itertools::assert_equal(it.clone(), vec![Ok(0), Ok(1), Err(false), Ok(2), Ok(3)]);
// This can also be used to propagate errors when collecting.
let output_result: Result<Vec<i32>, bool> = it.collect();
assert_eq!(output_result, Err(false));
sourcefn process_results<F, T, E, R>(self, processor: F) -> Result<R, E>
fn process_results<F, T, E, R>(self, processor: F) -> Result<R, E>
“Lift” a function of the values of the current iterator so as to process
an iterator of Result
values instead.
processor
is a closure that receives an adapted version of the iterator
as the only argument — the adapted iterator produces elements of type T
,
as long as the original iterator produces Ok
values.
If the original iterable produces an error at any point, the adapted iterator ends and it will return the error iself.
Otherwise, the return value from the closure is returned wrapped
inside Ok
.
§Example
use itertools::Itertools;
type Item = Result<i32, &'static str>;
let first_values: Vec<Item> = vec![Ok(1), Ok(0), Ok(3)];
let second_values: Vec<Item> = vec![Ok(2), Ok(1), Err("overflow")];
// “Lift” the iterator .max() method to work on the Ok-values.
let first_max = first_values.into_iter().process_results(|iter| iter.max().unwrap_or(0));
let second_max = second_values.into_iter().process_results(|iter| iter.max().unwrap_or(0));
assert_eq!(first_max, Ok(3));
assert!(second_max.is_err());
sourcefn merge<J>(self, other: J) -> Merge<Self, J::IntoIter>
fn merge<J>(self, other: J) -> Merge<Self, J::IntoIter>
Return an iterator adaptor that merges the two base iterators in ascending order. If both base iterators are sorted (ascending), the result is sorted.
Iterator element type is Self::Item
.
use itertools::Itertools;
let a = (0..11).step_by(3);
let b = (0..11).step_by(5);
let it = a.merge(b);
itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]);
sourcefn merge_by<J, F>(self, other: J, is_first: F) -> MergeBy<Self, J::IntoIter, F> ⓘ
fn merge_by<J, F>(self, other: J, is_first: F) -> MergeBy<Self, J::IntoIter, F> ⓘ
Return an iterator adaptor that merges the two base iterators in order.
This is much like .merge()
but allows for a custom ordering.
This can be especially useful for sequences of tuples.
Iterator element type is Self::Item
.
use itertools::Itertools;
let a = (0..).zip("bc".chars());
let b = (0..).zip("ad".chars());
let it = a.merge_by(b, |x, y| x.1 <= y.1);
itertools::assert_equal(it, vec![(0, 'a'), (0, 'b'), (1, 'c'), (1, 'd')]);
sourcefn merge_join_by<J, F, T>(
self,
other: J,
cmp_fn: F,
) -> MergeJoinBy<Self, J::IntoIter, F>
fn merge_join_by<J, F, T>( self, other: J, cmp_fn: F, ) -> MergeJoinBy<Self, J::IntoIter, F>
Create an iterator that merges items from both this and the specified iterator in ascending order.
The function can either return an Ordering
variant or a boolean.
If cmp_fn
returns Ordering
,
it chooses whether to pair elements based on the Ordering
returned by the
specified compare function. At any point, inspecting the tip of the
iterators I
and J
as items i
of type I::Item
and j
of type
J::Item
respectively, the resulting iterator will:
- Emit
EitherOrBoth::Left(i)
wheni < j
, and removei
from its source iterator - Emit
EitherOrBoth::Right(j)
wheni > j
, and removej
from its source iterator - Emit
EitherOrBoth::Both(i, j)
wheni == j
, and remove bothi
andj
from their respective source iterators
use itertools::Itertools;
use itertools::EitherOrBoth::{Left, Right, Both};
let a = vec![0, 2, 4, 6, 1].into_iter();
let b = (0..10).step_by(3);
itertools::assert_equal(
a.merge_join_by(b, |i, j| i.cmp(j)),
vec![Both(0, 0), Left(2), Right(3), Left(4), Both(6, 6), Left(1), Right(9)]
);
If cmp_fn
returns bool
,
it chooses whether to pair elements based on the boolean returned by the
specified function. At any point, inspecting the tip of the
iterators I
and J
as items i
of type I::Item
and j
of type
J::Item
respectively, the resulting iterator will:
- Emit
Either::Left(i)
whentrue
, and removei
from its source iterator - Emit
Either::Right(j)
whenfalse
, and removej
from its source iterator
It is similar to the Ordering
case if the first argument is considered
“less” than the second argument.
use itertools::Itertools;
use itertools::Either::{Left, Right};
let a = vec![0, 2, 4, 6, 1].into_iter();
let b = (0..10).step_by(3);
itertools::assert_equal(
a.merge_join_by(b, |i, j| i <= j),
vec![Left(0), Right(0), Left(2), Right(3), Left(4), Left(6), Left(1), Right(6), Right(9)]
);
sourcefn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter>
fn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter>
Return an iterator adaptor that flattens an iterator of iterators by merging them in ascending order.
If all base iterators are sorted (ascending), the result is sorted.
Iterator element type is Self::Item
.
use itertools::Itertools;
let a = (0..6).step_by(3);
let b = (1..6).step_by(3);
let c = (2..6).step_by(3);
let it = vec![a, b, c].into_iter().kmerge();
itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]);
sourcefn kmerge_by<F>(
self,
first: F,
) -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F> ⓘwhere
Self: Sized,
Self::Item: IntoIterator,
F: FnMut(&<Self::Item as IntoIterator>::Item, &<Self::Item as IntoIterator>::Item) -> bool,
fn kmerge_by<F>(
self,
first: F,
) -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F> ⓘwhere
Self: Sized,
Self::Item: IntoIterator,
F: FnMut(&<Self::Item as IntoIterator>::Item, &<Self::Item as IntoIterator>::Item) -> bool,
Return an iterator adaptor that flattens an iterator of iterators by merging them according to the given closure.
The closure first
is called with two elements a, b and should
return true
if a is ordered before b.
If all base iterators are sorted according to first
, the result is
sorted.
Iterator element type is Self::Item
.
use itertools::Itertools;
let a = vec![-1f64, 2., 3., -5., 6., -7.];
let b = vec![0., 2., -4.];
let mut it = vec![a, b].into_iter().kmerge_by(|a, b| a.abs() < b.abs());
assert_eq!(it.next(), Some(0.));
assert_eq!(it.last(), Some(-7.));
sourcefn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoIter> ⓘ
fn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoIter> ⓘ
Return an iterator adaptor that iterates over the cartesian product of
the element sets of two iterators self
and J
.
Iterator element type is (Self::Item, J::Item)
.
use itertools::Itertools;
let it = (0..2).cartesian_product("αβ".chars());
itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]);
sourcefn multi_cartesian_product(
self,
) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter> ⓘwhere
Self: Sized,
Self::Item: IntoIterator,
<Self::Item as IntoIterator>::IntoIter: Clone,
<Self::Item as IntoIterator>::Item: Clone,
fn multi_cartesian_product(
self,
) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter> ⓘwhere
Self: Sized,
Self::Item: IntoIterator,
<Self::Item as IntoIterator>::IntoIter: Clone,
<Self::Item as IntoIterator>::Item: Clone,
Return an iterator adaptor that iterates over the cartesian product of
all subiterators returned by meta-iterator self
.
All provided iterators must yield the same Item
type. To generate
the product of iterators yielding multiple types, use the
iproduct
macro instead.
The iterator element type is Vec<T>
, where T
is the iterator element
of the subiterators.
Note that the iterator is fused.
use itertools::Itertools;
let mut multi_prod = (0..3).map(|i| (i * 2)..(i * 2 + 2))
.multi_cartesian_product();
assert_eq!(multi_prod.next(), Some(vec![0, 2, 4]));
assert_eq!(multi_prod.next(), Some(vec![0, 2, 5]));
assert_eq!(multi_prod.next(), Some(vec![0, 3, 4]));
assert_eq!(multi_prod.next(), Some(vec![0, 3, 5]));
assert_eq!(multi_prod.next(), Some(vec![1, 2, 4]));
assert_eq!(multi_prod.next(), Some(vec![1, 2, 5]));
assert_eq!(multi_prod.next(), Some(vec![1, 3, 4]));
assert_eq!(multi_prod.next(), Some(vec![1, 3, 5]));
assert_eq!(multi_prod.next(), None);
If the adapted iterator is empty, the result is an iterator yielding a single empty vector. This is known as the nullary cartesian product.
use itertools::Itertools;
let mut nullary_cartesian_product = (0..0).map(|i| (i * 2)..(i * 2 + 2)).multi_cartesian_product();
assert_eq!(nullary_cartesian_product.next(), Some(vec![]));
assert_eq!(nullary_cartesian_product.next(), None);
sourcefn coalesce<F>(self, f: F) -> Coalesce<Self, F>
fn coalesce<F>(self, f: F) -> Coalesce<Self, F>
Return an iterator adaptor that uses the passed-in closure to optionally merge together consecutive elements.
The closure f
is passed two elements, previous
and current
and may
return either (1) Ok(combined)
to merge the two values or
(2) Err((previous', current'))
to indicate they can’t be merged.
In (2), the value previous'
is emitted by the iterator.
Either (1) combined
or (2) current'
becomes the previous value
when coalesce continues with the next pair of elements to merge. The
value that remains at the end is also emitted by the iterator.
Iterator element type is Self::Item
.
This iterator is fused.
use itertools::Itertools;
// sum same-sign runs together
let data = vec![-1., -2., -3., 3., 1., 0., -1.];
itertools::assert_equal(data.into_iter().coalesce(|x, y|
if (x >= 0.) == (y >= 0.) {
Ok(x + y)
} else {
Err((x, y))
}),
vec![-6., 4., -1.]);
sourcefn dedup(self) -> Dedup<Self>
fn dedup(self) -> Dedup<Self>
Remove duplicates from sections of consecutive identical elements. If the iterator is sorted, all elements will be unique.
Iterator element type is Self::Item
.
This iterator is fused.
use itertools::Itertools;
let data = vec![1., 1., 2., 3., 3., 2., 2.];
itertools::assert_equal(data.into_iter().dedup(),
vec![1., 2., 3., 2.]);
sourcefn dedup_by<Cmp>(self, cmp: Cmp) -> DedupBy<Self, Cmp>
fn dedup_by<Cmp>(self, cmp: Cmp) -> DedupBy<Self, Cmp>
Remove duplicates from sections of consecutive identical elements, determining equality using a comparison function. If the iterator is sorted, all elements will be unique.
Iterator element type is Self::Item
.
This iterator is fused.
use itertools::Itertools;
let data = vec![(0, 1.), (1, 1.), (0, 2.), (0, 3.), (1, 3.), (1, 2.), (2, 2.)];
itertools::assert_equal(data.into_iter().dedup_by(|x, y| x.1 == y.1),
vec![(0, 1.), (0, 2.), (0, 3.), (1, 2.)]);
sourcefn dedup_with_count(self) -> DedupWithCount<Self>where
Self: Sized,
fn dedup_with_count(self) -> DedupWithCount<Self>where
Self: Sized,
Remove duplicates from sections of consecutive identical elements, while keeping a count of how many repeated elements were present. If the iterator is sorted, all elements will be unique.
Iterator element type is (usize, Self::Item)
.
This iterator is fused.
use itertools::Itertools;
let data = vec!['a', 'a', 'b', 'c', 'c', 'b', 'b'];
itertools::assert_equal(data.into_iter().dedup_with_count(),
vec![(2, 'a'), (1, 'b'), (2, 'c'), (2, 'b')]);
sourcefn dedup_by_with_count<Cmp>(self, cmp: Cmp) -> DedupByWithCount<Self, Cmp>
fn dedup_by_with_count<Cmp>(self, cmp: Cmp) -> DedupByWithCount<Self, Cmp>
Remove duplicates from sections of consecutive identical elements, while keeping a count of how many repeated elements were present. This will determine equality using a comparison function. If the iterator is sorted, all elements will be unique.
Iterator element type is (usize, Self::Item)
.
This iterator is fused.
use itertools::Itertools;
let data = vec![(0, 'a'), (1, 'a'), (0, 'b'), (0, 'c'), (1, 'c'), (1, 'b'), (2, 'b')];
itertools::assert_equal(data.into_iter().dedup_by_with_count(|x, y| x.1 == y.1),
vec![(2, (0, 'a')), (1, (0, 'b')), (2, (0, 'c')), (2, (1, 'b'))]);
sourcefn duplicates(self) -> Duplicates<Self>
fn duplicates(self) -> Duplicates<Self>
Return an iterator adaptor that produces elements that appear more than once during the iteration. Duplicates are detected using hash and equality.
The iterator is stable, returning the duplicate items in the order in which they occur in the adapted iterator. Each duplicate item is returned exactly once. If an item appears more than twice, the second item is the item retained and the rest are discarded.
use itertools::Itertools;
let data = vec![10, 20, 30, 20, 40, 10, 50];
itertools::assert_equal(data.into_iter().duplicates(),
vec![20, 10]);
sourcefn duplicates_by<V, F>(self, f: F) -> DuplicatesBy<Self, V, F>
fn duplicates_by<V, F>(self, f: F) -> DuplicatesBy<Self, V, F>
Return an iterator adaptor that produces elements that appear more than once during the iteration. Duplicates are detected using hash and equality.
Duplicates are detected by comparing the key they map to with the keying function f
by
hash and equality. The keys are stored in a hash map in the iterator.
The iterator is stable, returning the duplicate items in the order in which they occur in the adapted iterator. Each duplicate item is returned exactly once. If an item appears more than twice, the second item is the item retained and the rest are discarded.
use itertools::Itertools;
let data = vec!["a", "bb", "aa", "c", "ccc"];
itertools::assert_equal(data.into_iter().duplicates_by(|s| s.len()),
vec!["aa", "c"]);
sourcefn unique(self) -> Unique<Self> ⓘ
fn unique(self) -> Unique<Self> ⓘ
Return an iterator adaptor that filters out elements that have already been produced once during the iteration. Duplicates are detected using hash and equality.
Clones of visited elements are stored in a hash set in the iterator.
The iterator is stable, returning the non-duplicate items in the order in which they occur in the adapted iterator. In a set of duplicate items, the first item encountered is the item retained.
use itertools::Itertools;
let data = vec![10, 20, 30, 20, 40, 10, 50];
itertools::assert_equal(data.into_iter().unique(),
vec![10, 20, 30, 40, 50]);
sourcefn unique_by<V, F>(self, f: F) -> UniqueBy<Self, V, F> ⓘ
fn unique_by<V, F>(self, f: F) -> UniqueBy<Self, V, F> ⓘ
Return an iterator adaptor that filters out elements that have already been produced once during the iteration.
Duplicates are detected by comparing the key they map to
with the keying function f
by hash and equality.
The keys are stored in a hash set in the iterator.
The iterator is stable, returning the non-duplicate items in the order in which they occur in the adapted iterator. In a set of duplicate items, the first item encountered is the item retained.
use itertools::Itertools;
let data = vec!["a", "bb", "aa", "c", "ccc"];
itertools::assert_equal(data.into_iter().unique_by(|s| s.len()),
vec!["a", "bb", "ccc"]);
sourcefn peeking_take_while<F>(&mut self, accept: F) -> PeekingTakeWhile<'_, Self, F> ⓘ
fn peeking_take_while<F>(&mut self, accept: F) -> PeekingTakeWhile<'_, Self, F> ⓘ
Return an iterator adaptor that borrows from this iterator and
takes items while the closure accept
returns true
.
This adaptor can only be used on iterators that implement PeekingNext
like .peekable()
, put_back
and a few other collection iterators.
The last and rejected element (first false
) is still available when
peeking_take_while
is done.
See also .take_while_ref()
which is a similar adaptor.
sourcefn take_while_ref<F>(&mut self, accept: F) -> TakeWhileRef<'_, Self, F> ⓘ
fn take_while_ref<F>(&mut self, accept: F) -> TakeWhileRef<'_, Self, F> ⓘ
Return an iterator adaptor that borrows from a Clone
-able iterator
to only pick off elements while the predicate accept
returns true
.
It uses the Clone
trait to restore the original iterator so that the
last and rejected element (first false
) is still available when
take_while_ref
is done.
use itertools::Itertools;
let mut hexadecimals = "0123456789abcdef".chars();
let decimals = hexadecimals.take_while_ref(|c| c.is_numeric())
.collect::<String>();
assert_eq!(decimals, "0123456789");
assert_eq!(hexadecimals.next(), Some('a'));
sourcefn take_while_inclusive<F>(self, accept: F) -> TakeWhileInclusive<Self, F> ⓘ
fn take_while_inclusive<F>(self, accept: F) -> TakeWhileInclusive<Self, F> ⓘ
Returns an iterator adaptor that consumes elements while the given
predicate is true
, including the element for which the predicate
first returned false
.
The .take_while()
adaptor is useful
when you want items satisfying a predicate, but to know when to stop
taking elements, we have to consume that first element that doesn’t
satisfy the predicate. This adaptor includes that element where
.take_while()
would drop it.
The .take_while_ref()
adaptor
serves a similar purpose, but this adaptor doesn’t require Clone
ing
the underlying elements.
let items = vec![1, 2, 3, 4, 5];
let filtered: Vec<_> = items
.into_iter()
.take_while_inclusive(|&n| n % 3 != 0)
.collect();
assert_eq!(filtered, vec![1, 2, 3]);
let items = vec![1, 2, 3, 4, 5];
let take_while_inclusive_result: Vec<_> = items
.iter()
.copied()
.take_while_inclusive(|&n| n % 3 != 0)
.collect();
let take_while_result: Vec<_> = items
.into_iter()
.take_while(|&n| n % 3 != 0)
.collect();
assert_eq!(take_while_inclusive_result, vec![1, 2, 3]);
assert_eq!(take_while_result, vec![1, 2]);
// both iterators have the same items remaining at this point---the 3
// is lost from the `take_while` vec
#[derive(Debug, PartialEq)]
struct NoCloneImpl(i32);
let non_clonable_items: Vec<_> = vec![1, 2, 3, 4, 5]
.into_iter()
.map(NoCloneImpl)
.collect();
let filtered: Vec<_> = non_clonable_items
.into_iter()
.take_while_inclusive(|n| n.0 % 3 != 0)
.collect();
let expected: Vec<_> = vec![1, 2, 3].into_iter().map(NoCloneImpl).collect();
assert_eq!(filtered, expected);
sourcefn while_some<A>(self) -> WhileSome<Self> ⓘ
fn while_some<A>(self) -> WhileSome<Self> ⓘ
Return an iterator adaptor that filters Option<A>
iterator elements
and produces A
. Stops on the first None
encountered.
Iterator element type is A
, the unwrapped element.
use itertools::Itertools;
// List all hexadecimal digits
itertools::assert_equal(
(0..).map(|i| std::char::from_digit(i, 16)).while_some(),
"0123456789abcdef".chars());
sourcefn tuple_combinations<T>(self) -> TupleCombinations<Self, T> ⓘ
fn tuple_combinations<T>(self) -> TupleCombinations<Self, T> ⓘ
Return an iterator adaptor that iterates over the combinations of the elements from an iterator.
Iterator element can be any homogeneous tuple of type Self::Item
with
size up to 12.
§Guarantees
If the adapted iterator is deterministic, this iterator adapter yields items in a reliable order.
use itertools::Itertools;
let mut v = Vec::new();
for (a, b) in (1..5).tuple_combinations() {
v.push((a, b));
}
assert_eq!(v, vec![(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]);
let mut it = (1..5).tuple_combinations();
assert_eq!(Some((1, 2, 3)), it.next());
assert_eq!(Some((1, 2, 4)), it.next());
assert_eq!(Some((1, 3, 4)), it.next());
assert_eq!(Some((2, 3, 4)), it.next());
assert_eq!(None, it.next());
// this requires a type hint
let it = (1..5).tuple_combinations::<(_, _, _)>();
itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]);
// you can also specify the complete type
use itertools::TupleCombinations;
use std::ops::Range;
let it: TupleCombinations<Range<u32>, (u32, u32, u32)> = (1..5).tuple_combinations();
itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]);
sourcefn combinations(self, k: usize) -> Combinations<Self> ⓘ
fn combinations(self, k: usize) -> Combinations<Self> ⓘ
Return an iterator adaptor that iterates over the k
-length combinations of
the elements from an iterator.
Iterator element type is Vec<Self::Item>
. The iterator produces a new Vec
per iteration,
and clones the iterator elements.
§Guarantees
If the adapted iterator is deterministic, this iterator adapter yields items in a reliable order.
use itertools::Itertools;
let it = (1..5).combinations(3);
itertools::assert_equal(it, vec![
vec![1, 2, 3],
vec![1, 2, 4],
vec![1, 3, 4],
vec![2, 3, 4],
]);
Note: Combinations does not take into account the equality of the iterated values.
use itertools::Itertools;
let it = vec![1, 2, 2].into_iter().combinations(2);
itertools::assert_equal(it, vec![
vec![1, 2], // Note: these are the same
vec![1, 2], // Note: these are the same
vec![2, 2],
]);
sourcefn combinations_with_replacement(
self,
k: usize,
) -> CombinationsWithReplacement<Self> ⓘ
fn combinations_with_replacement( self, k: usize, ) -> CombinationsWithReplacement<Self> ⓘ
Return an iterator that iterates over the k
-length combinations of
the elements from an iterator, with replacement.
Iterator element type is Vec<Self::Item>
. The iterator produces a new Vec
per iteration,
and clones the iterator elements.
use itertools::Itertools;
let it = (1..4).combinations_with_replacement(2);
itertools::assert_equal(it, vec![
vec![1, 1],
vec![1, 2],
vec![1, 3],
vec![2, 2],
vec![2, 3],
vec![3, 3],
]);
sourcefn permutations(self, k: usize) -> Permutations<Self> ⓘ
fn permutations(self, k: usize) -> Permutations<Self> ⓘ
Return an iterator adaptor that iterates over all k-permutations of the elements from an iterator.
Iterator element type is Vec<Self::Item>
with length k
. The iterator
produces a new Vec
per iteration, and clones the iterator elements.
If k
is greater than the length of the input iterator, the resultant
iterator adaptor will be empty.
If you are looking for permutations with replacements,
use repeat_n(iter, k).multi_cartesian_product()
instead.
use itertools::Itertools;
let perms = (5..8).permutations(2);
itertools::assert_equal(perms, vec![
vec![5, 6],
vec![5, 7],
vec![6, 5],
vec![6, 7],
vec![7, 5],
vec![7, 6],
]);
Note: Permutations does not take into account the equality of the iterated values.
use itertools::Itertools;
let it = vec![2, 2].into_iter().permutations(2);
itertools::assert_equal(it, vec![
vec![2, 2], // Note: these are the same
vec![2, 2], // Note: these are the same
]);
Note: The source iterator is collected lazily, and will not be re-iterated if the permutations adaptor is completed and re-iterated.
sourcefn powerset(self) -> Powerset<Self> ⓘ
fn powerset(self) -> Powerset<Self> ⓘ
Return an iterator that iterates through the powerset of the elements from an iterator.
Iterator element type is Vec<Self::Item>
. The iterator produces a new Vec
per iteration, and clones the iterator elements.
The powerset of a set contains all subsets including the empty set and the full input set. A powerset has length 2^n where n is the length of the input set.
Each Vec
produced by this iterator represents a subset of the elements
produced by the source iterator.
use itertools::Itertools;
let sets = (1..4).powerset().collect::<Vec<_>>();
itertools::assert_equal(sets, vec![
vec![],
vec![1],
vec![2],
vec![3],
vec![1, 2],
vec![1, 3],
vec![2, 3],
vec![1, 2, 3],
]);
sourcefn pad_using<F>(self, min: usize, f: F) -> PadUsing<Self, F> ⓘ
fn pad_using<F>(self, min: usize, f: F) -> PadUsing<Self, F> ⓘ
Return an iterator adaptor that pads the sequence to a minimum length of
min
by filling missing elements using a closure f
.
Iterator element type is Self::Item
.
use itertools::Itertools;
let it = (0..5).pad_using(10, |i| 2*i);
itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 10, 12, 14, 16, 18]);
let it = (0..10).pad_using(5, |i| 2*i);
itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let it = (0..5).pad_using(10, |i| 2*i).rev();
itertools::assert_equal(it, vec![18, 16, 14, 12, 10, 4, 3, 2, 1, 0]);
sourcefn with_position(self) -> WithPosition<Self> ⓘwhere
Self: Sized,
fn with_position(self) -> WithPosition<Self> ⓘwhere
Self: Sized,
Return an iterator adaptor that combines each element with a Position
to
ease special-case handling of the first or last elements.
Iterator element type is
(Position, Self::Item)
use itertools::{Itertools, Position};
let it = (0..4).with_position();
itertools::assert_equal(it,
vec![(Position::First, 0),
(Position::Middle, 1),
(Position::Middle, 2),
(Position::Last, 3)]);
let it = (0..1).with_position();
itertools::assert_equal(it, vec![(Position::Only, 0)]);
sourcefn positions<P>(self, predicate: P) -> Positions<Self, P> ⓘ
fn positions<P>(self, predicate: P) -> Positions<Self, P> ⓘ
Return an iterator adaptor that yields the indices of all elements satisfying a predicate, counted from the start of the iterator.
Equivalent to iter.enumerate().filter(|(_, v)| predicate(*v)).map(|(i, _)| i)
.
use itertools::Itertools;
let data = vec![1, 2, 3, 3, 4, 6, 7, 9];
itertools::assert_equal(data.iter().positions(|v| v % 2 == 0), vec![1, 4, 5]);
itertools::assert_equal(data.iter().positions(|v| v % 2 == 1).rev(), vec![7, 6, 3, 2, 0]);
sourcefn update<F>(self, updater: F) -> Update<Self, F> ⓘ
fn update<F>(self, updater: F) -> Update<Self, F> ⓘ
Return an iterator adaptor that applies a mutating function to each element before yielding it.
use itertools::Itertools;
let input = vec![vec![1], vec![3, 2, 1]];
let it = input.into_iter().update(|mut v| v.push(0));
itertools::assert_equal(it, vec![vec![1, 0], vec![3, 2, 1, 0]]);
sourcefn next_tuple<T>(&mut self) -> Option<T>
fn next_tuple<T>(&mut self) -> Option<T>
Advances the iterator and returns the next items grouped in a tuple of a specific size (up to 12).
If there are enough elements to be grouped in a tuple, then the tuple is
returned inside Some
, otherwise None
is returned.
use itertools::Itertools;
let mut iter = 1..5;
assert_eq!(Some((1, 2)), iter.next_tuple());
sourcefn collect_tuple<T>(self) -> Option<T>
fn collect_tuple<T>(self) -> Option<T>
Collects all items from the iterator into a tuple of a specific size (up to 12).
If the number of elements inside the iterator is exactly equal to
the tuple size, then the tuple is returned inside Some
, otherwise
None
is returned.
use itertools::Itertools;
let iter = 1..3;
if let Some((x, y)) = iter.collect_tuple() {
assert_eq!((x, y), (1, 2))
} else {
panic!("Expected two elements")
}
sourcefn find_position<P>(&mut self, pred: P) -> Option<(usize, Self::Item)>
fn find_position<P>(&mut self, pred: P) -> Option<(usize, Self::Item)>
Find the position and value of the first element satisfying a predicate.
The iterator is not advanced past the first element found.
use itertools::Itertools;
let text = "Hα";
assert_eq!(text.chars().find_position(|ch| ch.is_lowercase()), Some((1, 'α')));
sourcefn find_or_last<P>(self, predicate: P) -> Option<Self::Item>
fn find_or_last<P>(self, predicate: P) -> Option<Self::Item>
Find the value of the first element satisfying a predicate or return the last element, if any.
The iterator is not advanced past the first element found.
use itertools::Itertools;
let numbers = [1, 2, 3, 4];
assert_eq!(numbers.iter().find_or_last(|&&x| x > 5), Some(&4));
assert_eq!(numbers.iter().find_or_last(|&&x| x > 2), Some(&3));
assert_eq!(std::iter::empty::<i32>().find_or_last(|&x| x > 5), None);
sourcefn find_or_first<P>(self, predicate: P) -> Option<Self::Item>
fn find_or_first<P>(self, predicate: P) -> Option<Self::Item>
Find the value of the first element satisfying a predicate or return the first element, if any.
The iterator is not advanced past the first element found.
use itertools::Itertools;
let numbers = [1, 2, 3, 4];
assert_eq!(numbers.iter().find_or_first(|&&x| x > 5), Some(&1));
assert_eq!(numbers.iter().find_or_first(|&&x| x > 2), Some(&3));
assert_eq!(std::iter::empty::<i32>().find_or_first(|&x| x > 5), None);
sourcefn contains<Q>(&mut self, query: &Q) -> bool
fn contains<Q>(&mut self, query: &Q) -> bool
Returns true
if the given item is present in this iterator.
This method is short-circuiting. If the given item is present in this iterator, this method will consume the iterator up-to-and-including the item. If the given item is not present in this iterator, the iterator will be exhausted.
use itertools::Itertools;
#[derive(PartialEq, Debug)]
enum Enum { A, B, C, D, E, }
let mut iter = vec![Enum::A, Enum::B, Enum::C, Enum::D].into_iter();
// search `iter` for `B`
assert_eq!(iter.contains(&Enum::B), true);
// `B` was found, so the iterator now rests at the item after `B` (i.e, `C`).
assert_eq!(iter.next(), Some(Enum::C));
// search `iter` for `E`
assert_eq!(iter.contains(&Enum::E), false);
// `E` wasn't found, so `iter` is now exhausted
assert_eq!(iter.next(), None);
sourcefn all_equal(&mut self) -> bool
fn all_equal(&mut self) -> bool
Check whether all elements compare equal.
Empty iterators are considered to have equal elements:
use itertools::Itertools;
let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5];
assert!(!data.iter().all_equal());
assert!(data[0..3].iter().all_equal());
assert!(data[3..5].iter().all_equal());
assert!(data[5..8].iter().all_equal());
let data : Option<usize> = None;
assert!(data.into_iter().all_equal());
sourcefn all_equal_value(
&mut self,
) -> Result<Self::Item, Option<(Self::Item, Self::Item)>>
fn all_equal_value( &mut self, ) -> Result<Self::Item, Option<(Self::Item, Self::Item)>>
If there are elements and they are all equal, return a single copy of that element. If there are no elements, return an Error containing None. If there are elements and they are not all equal, return a tuple containing the first two non-equal elements found.
use itertools::Itertools;
let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5];
assert_eq!(data.iter().all_equal_value(), Err(Some((&1, &2))));
assert_eq!(data[0..3].iter().all_equal_value(), Ok(&1));
assert_eq!(data[3..5].iter().all_equal_value(), Ok(&2));
assert_eq!(data[5..8].iter().all_equal_value(), Ok(&3));
let data : Option<usize> = None;
assert_eq!(data.into_iter().all_equal_value(), Err(None));
sourcefn all_unique(&mut self) -> bool
fn all_unique(&mut self) -> bool
Check whether all elements are unique (non equal).
Empty iterators are considered to have unique elements:
use itertools::Itertools;
let data = vec![1, 2, 3, 4, 1, 5];
assert!(!data.iter().all_unique());
assert!(data[0..4].iter().all_unique());
assert!(data[1..6].iter().all_unique());
let data : Option<usize> = None;
assert!(data.into_iter().all_unique());
sourcefn dropping(self, n: usize) -> Selfwhere
Self: Sized,
fn dropping(self, n: usize) -> Selfwhere
Self: Sized,
Consume the first n
elements from the iterator eagerly,
and return the same iterator again.
It works similarly to .skip(n)
except it is eager and
preserves the iterator type.
use itertools::Itertools;
let mut iter = "αβγ".chars().dropping(2);
itertools::assert_equal(iter, "γ".chars());
Fusing notes: if the iterator is exhausted by dropping,
the result of calling .next()
again depends on the iterator implementation.
sourcefn dropping_back(self, n: usize) -> Selfwhere
Self: Sized + DoubleEndedIterator,
fn dropping_back(self, n: usize) -> Selfwhere
Self: Sized + DoubleEndedIterator,
Consume the last n
elements from the iterator eagerly,
and return the same iterator again.
This is only possible on double ended iterators. n
may be
larger than the number of elements.
Note: This method is eager, dropping the back elements immediately and preserves the iterator type.
use itertools::Itertools;
let init = vec![0, 3, 6, 9].into_iter().dropping_back(1);
itertools::assert_equal(init, vec![0, 3, 6]);
sourcefn concat(self) -> Self::Itemwhere
Self: Sized,
Self::Item: Extend<<<Self as Iterator>::Item as IntoIterator>::Item> + IntoIterator + Default,
fn concat(self) -> Self::Itemwhere
Self: Sized,
Self::Item: Extend<<<Self as Iterator>::Item as IntoIterator>::Item> + IntoIterator + Default,
Combine all an iterator’s elements into one element by using Extend
.
This combinator will extend the first item with each of the rest of the
items of the iterator. If the iterator is empty, the default value of
I::Item
is returned.
use itertools::Itertools;
let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]];
assert_eq!(input.into_iter().concat(),
vec![1, 2, 3, 4, 5, 6]);
sourcefn collect_vec(self) -> Vec<Self::Item>where
Self: Sized,
fn collect_vec(self) -> Vec<Self::Item>where
Self: Sized,
.collect_vec()
is simply a type specialization of Iterator::collect
,
for convenience.
sourcefn try_collect<T, U, E>(self) -> Result<U, E>
fn try_collect<T, U, E>(self) -> Result<U, E>
.try_collect()
is more convenient way of writing
.collect::<Result<_, _>>()
§Example
use std::{fs, io};
use itertools::Itertools;
fn process_dir_entries(entries: &[fs::DirEntry]) {
// ...
}
fn do_stuff() -> std::io::Result<()> {
let entries: Vec<_> = fs::read_dir(".")?.try_collect()?;
process_dir_entries(&entries);
Ok(())
}
sourcefn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize
fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize
Assign to each reference in self
from the from
iterator,
stopping at the shortest of the two iterators.
The from
iterator is queried for its next element before the self
iterator, and if either is exhausted the method is done.
Return the number of elements written.
use itertools::Itertools;
let mut xs = [0; 4];
xs.iter_mut().set_from(1..);
assert_eq!(xs, [1, 2, 3, 4]);
sourcefn join(&mut self, sep: &str) -> String
fn join(&mut self, sep: &str) -> String
Combine all iterator elements into one String
, separated by sep
.
Use the Display
implementation of each element.
use itertools::Itertools;
assert_eq!(["a", "b", "c"].iter().join(", "), "a, b, c");
assert_eq!([1, 2, 3].iter().join(", "), "1, 2, 3");
sourcefn format(self, sep: &str) -> Format<'_, Self>where
Self: Sized,
fn format(self, sep: &str) -> Format<'_, Self>where
Self: Sized,
Format all iterator elements, separated by sep
.
All elements are formatted (any formatting trait)
with sep
inserted between each element.
Panics if the formatter helper is formatted more than once.
use itertools::Itertools;
let data = [1.1, 2.71828, -3.];
assert_eq!(
format!("{:.2}", data.iter().format(", ")),
"1.10, 2.72, -3.00");
sourcefn format_with<F>(self, sep: &str, format: F) -> FormatWith<'_, Self, F>
fn format_with<F>(self, sep: &str, format: F) -> FormatWith<'_, Self, F>
Format all iterator elements, separated by sep
.
This is a customizable version of .format()
.
The supplied closure format
is called once per iterator element,
with two arguments: the element and a callback that takes a
&Display
value, i.e. any reference to type that implements Display
.
Using &format_args!(...)
is the most versatile way to apply custom
element formatting. The callback can be called multiple times if needed.
Panics if the formatter helper is formatted more than once.
use itertools::Itertools;
let data = [1.1, 2.71828, -3.];
let data_formatter = data.iter().format_with(", ", |elt, f| f(&format_args!("{:.2}", elt)));
assert_eq!(format!("{}", data_formatter),
"1.10, 2.72, -3.00");
// .format_with() is recursively composable
let matrix = [[1., 2., 3.],
[4., 5., 6.]];
let matrix_formatter = matrix.iter().format_with("\n", |row, f| {
f(&row.iter().format_with(", ", |elt, g| g(&elt)))
});
assert_eq!(format!("{}", matrix_formatter),
"1, 2, 3\n4, 5, 6");
sourcefn fold_ok<A, E, B, F>(&mut self, start: B, f: F) -> Result<B, E>
fn fold_ok<A, E, B, F>(&mut self, start: B, f: F) -> Result<B, E>
Fold Result
values from an iterator.
Only Ok
values are folded. If no error is encountered, the folded
value is returned inside Ok
. Otherwise, the operation terminates
and returns the first Err
value it encounters. No iterator elements are
consumed after the first error.
The first accumulator value is the start
parameter.
Each iteration passes the accumulator value and the next value inside Ok
to the fold function f
and its return value becomes the new accumulator value.
For example the sequence Ok(1), Ok(2), Ok(3) will result in a computation like this:
let mut accum = start;
accum = f(accum, 1);
accum = f(accum, 2);
accum = f(accum, 3);
With a start
value of 0 and an addition as folding function,
this effectively results in ((0 + 1) + 2) + 3
use std::ops::Add;
use itertools::Itertools;
let values = [1, 2, -2, -1, 2, 1];
assert_eq!(
values.iter()
.map(Ok::<_, ()>)
.fold_ok(0, Add::add),
Ok(3)
);
assert!(
values.iter()
.map(|&x| if x >= 0 { Ok(x) } else { Err("Negative number") })
.fold_ok(0, Add::add)
.is_err()
);
sourcefn fold_options<A, B, F>(&mut self, start: B, f: F) -> Option<B>
fn fold_options<A, B, F>(&mut self, start: B, f: F) -> Option<B>
Fold Option
values from an iterator.
Only Some
values are folded. If no None
is encountered, the folded
value is returned inside Some
. Otherwise, the operation terminates
and returns None
. No iterator elements are consumed after the None
.
This is the Option
equivalent to fold_ok
.
use std::ops::Add;
use itertools::Itertools;
let mut values = vec![Some(1), Some(2), Some(-2)].into_iter();
assert_eq!(values.fold_options(5, Add::add), Some(5 + 1 + 2 - 2));
let mut more_values = vec![Some(2), None, Some(0)].into_iter();
assert!(more_values.fold_options(0, Add::add).is_none());
assert_eq!(more_values.next().unwrap(), Some(0));
sourcefn fold1<F>(self, f: F) -> Option<Self::Item>
👎Deprecated since 0.10.2: Use Iterator::reduce
instead
fn fold1<F>(self, f: F) -> Option<Self::Item>
Iterator::reduce
insteadAccumulator of the elements in the iterator.
Like .fold()
, without a base case. If the iterator is
empty, return None
. With just one element, return it.
Otherwise elements are accumulated in sequence using the closure f
.
use itertools::Itertools;
assert_eq!((0..10).fold1(|x, y| x + y).unwrap_or(0), 45);
assert_eq!((0..0).fold1(|x, y| x * y), None);
sourcefn tree_reduce<F>(self, f: F) -> Option<Self::Item>
fn tree_reduce<F>(self, f: F) -> Option<Self::Item>
Accumulate the elements in the iterator in a tree-like manner.
You can think of it as, while there’s more than one item, repeatedly combining adjacent items. It does so in bottom-up-merge-sort order, however, so that it needs only logarithmic stack space.
This produces a call tree like the following (where the calls under an item are done after reading that item):
1 2 3 4 5 6 7
│ │ │ │ │ │ │
└─f └─f └─f │
│ │ │ │
└───f └─f
│ │
└─────f
Which, for non-associative functions, will typically produce a different
result than the linear call tree used by Iterator::reduce
:
1 2 3 4 5 6 7
│ │ │ │ │ │ │
└─f─f─f─f─f─f
If f
is associative you should also decide carefully:
- if
f
is a trivial operation likeu32::wrapping_add
, prefer the normalIterator::reduce
instead since it will most likely result in the generation of simpler code because the compiler is able to optimize it - otherwise if
f
is non-trivial likeformat!
, you should usetree_reduce
since it reduces the number of operations fromO(n)
toO(ln(n))
Here “non-trivial” means:
- any allocating operation
- any function that is a composition of many operations
use itertools::Itertools;
// The same tree as above
let num_strings = (1..8).map(|x| x.to_string());
assert_eq!(num_strings.tree_reduce(|x, y| format!("f({}, {})", x, y)),
Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))")));
// Like fold1, an empty iterator produces None
assert_eq!((0..0).tree_reduce(|x, y| x * y), None);
// tree_reduce matches fold1 for associative operations...
assert_eq!((0..10).tree_reduce(|x, y| x + y),
(0..10).fold1(|x, y| x + y));
// ...but not for non-associative ones
assert_ne!((0..10).tree_reduce(|x, y| x - y),
(0..10).fold1(|x, y| x - y));
sourcefn tree_fold1<F>(self, f: F) -> Option<Self::Item>
👎Deprecated since 0.13.0: Use .tree_reduce() instead
fn tree_fold1<F>(self, f: F) -> Option<Self::Item>
See .tree_reduce()
.
sourcefn fold_while<B, F>(&mut self, init: B, f: F) -> FoldWhile<B>
fn fold_while<B, F>(&mut self, init: B, f: F) -> FoldWhile<B>
An iterator method that applies a function, producing a single, final value.
fold_while()
is basically equivalent to Iterator::fold
but with additional support for
early exit via short-circuiting.
use itertools::Itertools;
use itertools::FoldWhile::{Continue, Done};
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let mut result = 0;
// for loop:
for i in &numbers {
if *i > 5 {
break;
}
result = result + i;
}
// fold:
let result2 = numbers.iter().fold(0, |acc, x| {
if *x > 5 { acc } else { acc + x }
});
// fold_while:
let result3 = numbers.iter().fold_while(0, |acc, x| {
if *x > 5 { Done(acc) } else { Continue(acc + x) }
}).into_inner();
// they're the same
assert_eq!(result, result2);
assert_eq!(result2, result3);
The big difference between the computations of result2
and result3
is that while
fold()
called the provided closure for every item of the callee iterator,
fold_while()
actually stopped iterating as soon as it encountered Fold::Done(_)
.
sourcefn sum1<S>(self) -> Option<S>
fn sum1<S>(self) -> Option<S>
Iterate over the entire iterator and add all the elements.
An empty iterator returns None
, otherwise Some(sum)
.
§Panics
When calling sum1()
and a primitive integer type is being returned, this
method will panic if the computation overflows and debug assertions are
enabled.
§Examples
use itertools::Itertools;
let empty_sum = (1..1).sum1::<i32>();
assert_eq!(empty_sum, None);
let nonempty_sum = (1..11).sum1::<i32>();
assert_eq!(nonempty_sum, Some(55));
sourcefn product1<P>(self) -> Option<P>
fn product1<P>(self) -> Option<P>
Iterate over the entire iterator and multiply all the elements.
An empty iterator returns None
, otherwise Some(product)
.
§Panics
When calling product1()
and a primitive integer type is being returned,
method will panic if the computation overflows and debug assertions are
enabled.
§Examples
use itertools::Itertools;
let empty_product = (1..1).product1::<i32>();
assert_eq!(empty_product, None);
let nonempty_product = (1..11).product1::<i32>();
assert_eq!(nonempty_product, Some(3628800));
sourcefn sorted_unstable(self) -> IntoIter<Self::Item> ⓘ
fn sorted_unstable(self) -> IntoIter<Self::Item> ⓘ
Sort all iterator elements into a new iterator in ascending order.
Note: This consumes the entire iterator, uses the
slice::sort_unstable
method and returns the result as a new
iterator that owns its elements.
This sort is unstable (i.e., may reorder equal elements).
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
use itertools::Itertools;
// sort the letters of the text in ascending order
let text = "bdacfe";
itertools::assert_equal(text.chars().sorted_unstable(),
"abcdef".chars());
sourcefn sorted_unstable_by<F>(self, cmp: F) -> IntoIter<Self::Item> ⓘ
fn sorted_unstable_by<F>(self, cmp: F) -> IntoIter<Self::Item> ⓘ
Sort all iterator elements into a new iterator in ascending order.
Note: This consumes the entire iterator, uses the
slice::sort_unstable_by
method and returns the result as a new
iterator that owns its elements.
This sort is unstable (i.e., may reorder equal elements).
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
use itertools::Itertools;
// sort people in descending order by age
let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)];
let oldest_people_first = people
.into_iter()
.sorted_unstable_by(|a, b| Ord::cmp(&b.1, &a.1))
.map(|(person, _age)| person);
itertools::assert_equal(oldest_people_first,
vec!["Jill", "Jack", "Jane", "John"]);
sourcefn sorted_unstable_by_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
fn sorted_unstable_by_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
Sort all iterator elements into a new iterator in ascending order.
Note: This consumes the entire iterator, uses the
slice::sort_unstable_by_key
method and returns the result as a new
iterator that owns its elements.
This sort is unstable (i.e., may reorder equal elements).
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
use itertools::Itertools;
// sort people in descending order by age
let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)];
let oldest_people_first = people
.into_iter()
.sorted_unstable_by_key(|x| -x.1)
.map(|(person, _age)| person);
itertools::assert_equal(oldest_people_first,
vec!["Jill", "Jack", "Jane", "John"]);
sourcefn sorted(self) -> IntoIter<Self::Item> ⓘ
fn sorted(self) -> IntoIter<Self::Item> ⓘ
Sort all iterator elements into a new iterator in ascending order.
Note: This consumes the entire iterator, uses the
slice::sort
method and returns the result as a new
iterator that owns its elements.
This sort is stable (i.e., does not reorder equal elements).
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
use itertools::Itertools;
// sort the letters of the text in ascending order
let text = "bdacfe";
itertools::assert_equal(text.chars().sorted(),
"abcdef".chars());
sourcefn sorted_by<F>(self, cmp: F) -> IntoIter<Self::Item> ⓘ
fn sorted_by<F>(self, cmp: F) -> IntoIter<Self::Item> ⓘ
Sort all iterator elements into a new iterator in ascending order.
Note: This consumes the entire iterator, uses the
slice::sort_by
method and returns the result as a new
iterator that owns its elements.
This sort is stable (i.e., does not reorder equal elements).
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
use itertools::Itertools;
// sort people in descending order by age
let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)];
let oldest_people_first = people
.into_iter()
.sorted_by(|a, b| Ord::cmp(&b.1, &a.1))
.map(|(person, _age)| person);
itertools::assert_equal(oldest_people_first,
vec!["Jill", "Jack", "Jane", "John"]);
sourcefn sorted_by_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
fn sorted_by_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
Sort all iterator elements into a new iterator in ascending order.
Note: This consumes the entire iterator, uses the
slice::sort_by_key
method and returns the result as a new
iterator that owns its elements.
This sort is stable (i.e., does not reorder equal elements).
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
use itertools::Itertools;
// sort people in descending order by age
let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)];
let oldest_people_first = people
.into_iter()
.sorted_by_key(|x| -x.1)
.map(|(person, _age)| person);
itertools::assert_equal(oldest_people_first,
vec!["Jill", "Jack", "Jane", "John"]);
sourcefn sorted_by_cached_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
fn sorted_by_cached_key<K, F>(self, f: F) -> IntoIter<Self::Item> ⓘ
Sort all iterator elements into a new iterator in ascending order. The key function is called exactly once per key.
Note: This consumes the entire iterator, uses the
slice::sort_by_cached_key
method and returns the result as a new
iterator that owns its elements.
This sort is stable (i.e., does not reorder equal elements).
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
use itertools::Itertools;
// sort people in descending order by age
let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)];
let oldest_people_first = people
.into_iter()
.sorted_by_cached_key(|x| -x.1)
.map(|(person, _age)| person);
itertools::assert_equal(oldest_people_first,
vec!["Jill", "Jack", "Jane", "John"]);
sourcefn k_smallest(self, k: usize) -> IntoIter<Self::Item> ⓘ
fn k_smallest(self, k: usize) -> IntoIter<Self::Item> ⓘ
Sort the k smallest elements into a new iterator, in ascending order.
Note: This consumes the entire iterator, and returns the result
as a new iterator that owns its elements. If the input contains
less than k elements, the result is equivalent to self.sorted()
.
This is guaranteed to use k * sizeof(Self::Item) + O(1)
memory
and O(n log k)
time, with n
the number of elements in the input.
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
Note: This is functionally-equivalent to self.sorted().take(k)
but much more efficient.
use itertools::Itertools;
// A random permutation of 0..15
let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5];
let five_smallest = numbers
.into_iter()
.k_smallest(5);
itertools::assert_equal(five_smallest, 0..5);
sourcefn k_smallest_by<F>(self, k: usize, cmp: F) -> IntoIter<Self::Item> ⓘ
fn k_smallest_by<F>(self, k: usize, cmp: F) -> IntoIter<Self::Item> ⓘ
Sort the k smallest elements into a new iterator using the provided comparison.
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
This corresponds to self.sorted_by(cmp).take(k)
in the same way that
k_smallest
corresponds to self.sorted().take(k)
,
in both semantics and complexity.
Particularly, a custom heap implementation ensures the comparison is not cloned.
use itertools::Itertools;
// A random permutation of 0..15
let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5];
let five_smallest = numbers
.into_iter()
.k_smallest_by(5, |a, b| (a % 7).cmp(&(b % 7)).then(a.cmp(b)));
itertools::assert_equal(five_smallest, vec![0, 7, 14, 1, 8]);
sourcefn k_smallest_by_key<F, K>(self, k: usize, key: F) -> IntoIter<Self::Item> ⓘ
fn k_smallest_by_key<F, K>(self, k: usize, key: F) -> IntoIter<Self::Item> ⓘ
Return the elements producing the k smallest outputs of the provided function.
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
This corresponds to self.sorted_by_key(key).take(k)
in the same way that
k_smallest
corresponds to self.sorted().take(k)
,
in both semantics and complexity.
Particularly, a custom heap implementation ensures the comparison is not cloned.
use itertools::Itertools;
// A random permutation of 0..15
let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5];
let five_smallest = numbers
.into_iter()
.k_smallest_by_key(5, |n| (n % 7, *n));
itertools::assert_equal(five_smallest, vec![0, 7, 14, 1, 8]);
sourcefn k_largest(self, k: usize) -> IntoIter<Self::Item> ⓘ
fn k_largest(self, k: usize) -> IntoIter<Self::Item> ⓘ
Sort the k largest elements into a new iterator, in descending order.
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
It is semantically equivalent to k_smallest
with a reversed Ord
.
However, this is implemented with a custom binary heap which does not
have the same performance characteristics for very large Self::Item
.
use itertools::Itertools;
// A random permutation of 0..15
let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5];
let five_largest = numbers
.into_iter()
.k_largest(5);
itertools::assert_equal(five_largest, vec![14, 13, 12, 11, 10]);
sourcefn k_largest_by<F>(self, k: usize, cmp: F) -> IntoIter<Self::Item> ⓘ
fn k_largest_by<F>(self, k: usize, cmp: F) -> IntoIter<Self::Item> ⓘ
Sort the k largest elements into a new iterator using the provided comparison.
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
Functionally equivalent to k_smallest_by
with a reversed Ord
.
use itertools::Itertools;
// A random permutation of 0..15
let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5];
let five_largest = numbers
.into_iter()
.k_largest_by(5, |a, b| (a % 7).cmp(&(b % 7)).then(a.cmp(b)));
itertools::assert_equal(five_largest, vec![13, 6, 12, 5, 11]);
sourcefn k_largest_by_key<F, K>(self, k: usize, key: F) -> IntoIter<Self::Item> ⓘ
fn k_largest_by_key<F, K>(self, k: usize, key: F) -> IntoIter<Self::Item> ⓘ
Return the elements producing the k largest outputs of the provided function.
The sorted iterator, if directly collected to a Vec
, is converted
without any extra copying or allocation cost.
Functionally equivalent to k_smallest_by_key
with a reversed Ord
.
use itertools::Itertools;
// A random permutation of 0..15
let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5];
let five_largest = numbers
.into_iter()
.k_largest_by_key(5, |n| (n % 7, *n));
itertools::assert_equal(five_largest, vec![13, 6, 12, 5, 11]);
sourcefn tail(self, n: usize) -> IntoIter<Self::Item> ⓘwhere
Self: Sized,
fn tail(self, n: usize) -> IntoIter<Self::Item> ⓘwhere
Self: Sized,
Consumes the iterator and return an iterator of the last n
elements.
The iterator, if directly collected to a VecDeque
, is converted
without any extra copying or allocation cost.
If directly collected to a Vec
, it may need some data movement
but no re-allocation.
use itertools::{assert_equal, Itertools};
let v = vec![5, 9, 8, 4, 2, 12, 0];
assert_equal(v.iter().tail(3), &[2, 12, 0]);
assert_equal(v.iter().tail(10), &v);
assert_equal(v.iter().tail(1), v.iter().last());
assert_equal((0..100).tail(10), 90..100);
assert_equal((0..100).filter(|x| x % 3 == 0).tail(10), (72..100).step_by(3));
For double ended iterators without side-effects, you might prefer
.rev().take(n).rev()
to have a similar result (lazy and non-allocating)
without consuming the entire iterator.
sourcefn partition_map<A, B, F, L, R>(self, predicate: F) -> (A, B)
fn partition_map<A, B, F, L, R>(self, predicate: F) -> (A, B)
Collect all iterator elements into one of two
partitions. Unlike Iterator::partition
, each partition may
have a distinct type.
use itertools::{Itertools, Either};
let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)];
let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures
.into_iter()
.partition_map(|r| {
match r {
Ok(v) => Either::Left(v),
Err(v) => Either::Right(v),
}
});
assert_eq!(successes, [1, 2]);
assert_eq!(failures, [false, true]);
sourcefn partition_result<A, B, T, E>(self) -> (A, B)
fn partition_result<A, B, T, E>(self) -> (A, B)
Partition a sequence of Result
s into one list of all the Ok
elements
and another list of all the Err
elements.
use itertools::Itertools;
let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)];
let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures
.into_iter()
.partition_result();
assert_eq!(successes, [1, 2]);
assert_eq!(failures, [false, true]);
sourcefn into_group_map<K, V>(self) -> HashMap<K, Vec<V>>
fn into_group_map<K, V>(self) -> HashMap<K, Vec<V>>
Return a HashMap
of keys mapped to Vec
s of values. Keys and values
are taken from (Key, Value)
tuple pairs yielded by the input iterator.
Essentially a shorthand for .into_grouping_map().collect::<Vec<_>>()
.
use itertools::Itertools;
let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)];
let lookup = data.into_iter().into_group_map();
assert_eq!(lookup[&0], vec![10, 20]);
assert_eq!(lookup.get(&1), None);
assert_eq!(lookup[&2], vec![12, 42]);
assert_eq!(lookup[&3], vec![13, 33]);
sourcefn into_group_map_by<K, V, F>(self, f: F) -> HashMap<K, Vec<V>>
fn into_group_map_by<K, V, F>(self, f: F) -> HashMap<K, Vec<V>>
Return an Iterator
on a HashMap
. Keys mapped to Vec
s of values. The key is specified
in the closure.
Essentially a shorthand for .into_grouping_map_by(f).collect::<Vec<_>>()
.
use itertools::Itertools;
use std::collections::HashMap;
let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)];
let lookup: HashMap<u32,Vec<(u32, u32)>> =
data.clone().into_iter().into_group_map_by(|a| a.0);
assert_eq!(lookup[&0], vec![(0,10),(0,20)]);
assert_eq!(lookup.get(&1), None);
assert_eq!(lookup[&2], vec![(2,12), (2,42)]);
assert_eq!(lookup[&3], vec![(3,13), (3,33)]);
assert_eq!(
data.into_iter()
.into_group_map_by(|x| x.0)
.into_iter()
.map(|(key, values)| (key, values.into_iter().fold(0,|acc, (_,v)| acc + v )))
.collect::<HashMap<u32,u32>>()[&0],
30,
);
sourcefn into_grouping_map<K, V>(self) -> GroupingMap<Self>
fn into_grouping_map<K, V>(self) -> GroupingMap<Self>
Constructs a GroupingMap
to be used later with one of the efficient
group-and-fold operations it allows to perform.
The input iterator must yield item in the form of (K, V)
where the
value of type K
will be used as key to identify the groups and the
value of type V
as value for the folding operation.
See GroupingMap
for more informations
on what operations are available.
sourcefn into_grouping_map_by<K, V, F>(self, key_mapper: F) -> GroupingMapBy<Self, F>
fn into_grouping_map_by<K, V, F>(self, key_mapper: F) -> GroupingMapBy<Self, F>
Constructs a GroupingMap
to be used later with one of the efficient
group-and-fold operations it allows to perform.
The values from this iterator will be used as values for the folding operation
while the keys will be obtained from the values by calling key_mapper
.
See GroupingMap
for more informations
on what operations are available.
sourcefn min_set(self) -> Vec<Self::Item>
fn min_set(self) -> Vec<Self::Item>
Return all minimum elements of an iterator.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().min_set(), Vec::<&i32>::new());
let a = [1];
assert_eq!(a.iter().min_set(), vec![&1]);
let a = [1, 2, 3, 4, 5];
assert_eq!(a.iter().min_set(), vec![&1]);
let a = [1, 1, 1, 1];
assert_eq!(a.iter().min_set(), vec![&1, &1, &1, &1]);
The elements can be floats but no particular result is guaranteed if an element is NaN.
sourcefn min_set_by<F>(self, compare: F) -> Vec<Self::Item>
fn min_set_by<F>(self, compare: F) -> Vec<Self::Item>
Return all minimum elements of an iterator, as determined by the specified function.
§Examples
use itertools::Itertools;
let a: [(i32, i32); 0] = [];
assert_eq!(a.iter().min_set_by(|_, _| Ordering::Equal), Vec::<&(i32, i32)>::new());
let a = [(1, 2)];
assert_eq!(a.iter().min_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2)]);
let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
assert_eq!(a.iter().min_set_by(|&&(_,k1), &&(_,k2)| k1.cmp(&k2)), vec![&(1, 2), &(2, 2)]);
let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
assert_eq!(a.iter().min_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
The elements can be floats but no particular result is guaranteed if an element is NaN.
sourcefn min_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
fn min_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
Return all minimum elements of an iterator, as determined by the specified function.
§Examples
use itertools::Itertools;
let a: [(i32, i32); 0] = [];
assert_eq!(a.iter().min_set_by_key(|_| ()), Vec::<&(i32, i32)>::new());
let a = [(1, 2)];
assert_eq!(a.iter().min_set_by_key(|&&(k,_)| k), vec![&(1, 2)]);
let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
assert_eq!(a.iter().min_set_by_key(|&&(_, k)| k), vec![&(1, 2), &(2, 2)]);
let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
assert_eq!(a.iter().min_set_by_key(|&&(k, _)| k), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
The elements can be floats but no particular result is guaranteed if an element is NaN.
sourcefn max_set(self) -> Vec<Self::Item>
fn max_set(self) -> Vec<Self::Item>
Return all maximum elements of an iterator.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().max_set(), Vec::<&i32>::new());
let a = [1];
assert_eq!(a.iter().max_set(), vec![&1]);
let a = [1, 2, 3, 4, 5];
assert_eq!(a.iter().max_set(), vec![&5]);
let a = [1, 1, 1, 1];
assert_eq!(a.iter().max_set(), vec![&1, &1, &1, &1]);
The elements can be floats but no particular result is guaranteed if an element is NaN.
sourcefn max_set_by<F>(self, compare: F) -> Vec<Self::Item>
fn max_set_by<F>(self, compare: F) -> Vec<Self::Item>
Return all maximum elements of an iterator, as determined by the specified function.
§Examples
use itertools::Itertools;
let a: [(i32, i32); 0] = [];
assert_eq!(a.iter().max_set_by(|_, _| Ordering::Equal), Vec::<&(i32, i32)>::new());
let a = [(1, 2)];
assert_eq!(a.iter().max_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2)]);
let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
assert_eq!(a.iter().max_set_by(|&&(_,k1), &&(_,k2)| k1.cmp(&k2)), vec![&(3, 9), &(5, 9)]);
let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
assert_eq!(a.iter().max_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
The elements can be floats but no particular result is guaranteed if an element is NaN.
sourcefn max_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
fn max_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
Return all maximum elements of an iterator, as determined by the specified function.
§Examples
use itertools::Itertools;
let a: [(i32, i32); 0] = [];
assert_eq!(a.iter().max_set_by_key(|_| ()), Vec::<&(i32, i32)>::new());
let a = [(1, 2)];
assert_eq!(a.iter().max_set_by_key(|&&(k,_)| k), vec![&(1, 2)]);
let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
assert_eq!(a.iter().max_set_by_key(|&&(_, k)| k), vec![&(3, 9), &(5, 9)]);
let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
assert_eq!(a.iter().max_set_by_key(|&&(k, _)| k), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
The elements can be floats but no particular result is guaranteed if an element is NaN.
sourcefn minmax(self) -> MinMaxResult<Self::Item>
fn minmax(self) -> MinMaxResult<Self::Item>
Return the minimum and maximum elements in the iterator.
The return type MinMaxResult
is an enum of three variants:
NoElements
if the iterator is empty.OneElement(x)
if the iterator has exactly one element.MinMax(x, y)
is returned otherwise, wherex <= y
. Two values are equal if and only if there is more than one element in the iterator and all elements are equal.
On an iterator of length n
, minmax
does 1.5 * n
comparisons,
and so is faster than calling min
and max
separately which does
2 * n
comparisons.
§Examples
use itertools::Itertools;
use itertools::MinMaxResult::{NoElements, OneElement, MinMax};
let a: [i32; 0] = [];
assert_eq!(a.iter().minmax(), NoElements);
let a = [1];
assert_eq!(a.iter().minmax(), OneElement(&1));
let a = [1, 2, 3, 4, 5];
assert_eq!(a.iter().minmax(), MinMax(&1, &5));
let a = [1, 1, 1, 1];
assert_eq!(a.iter().minmax(), MinMax(&1, &1));
The elements can be floats but no particular result is guaranteed if an element is NaN.
sourcefn minmax_by_key<K, F>(self, key: F) -> MinMaxResult<Self::Item>
fn minmax_by_key<K, F>(self, key: F) -> MinMaxResult<Self::Item>
Return the minimum and maximum element of an iterator, as determined by the specified function.
The return value is a variant of MinMaxResult
like for .minmax()
.
For the minimum, the first minimal element is returned. For the maximum,
the last maximal element wins. This matches the behavior of the standard
Iterator::min
and Iterator::max
methods.
The keys can be floats but no particular result is guaranteed if a key is NaN.
sourcefn minmax_by<F>(self, compare: F) -> MinMaxResult<Self::Item>
fn minmax_by<F>(self, compare: F) -> MinMaxResult<Self::Item>
Return the minimum and maximum element of an iterator, as determined by the specified comparison function.
The return value is a variant of MinMaxResult
like for .minmax()
.
For the minimum, the first minimal element is returned. For the maximum,
the last maximal element wins. This matches the behavior of the standard
Iterator::min
and Iterator::max
methods.
sourcefn position_max(self) -> Option<usize>
fn position_max(self) -> Option<usize>
Return the position of the maximum element in the iterator.
If several elements are equally maximum, the position of the last of them is returned.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().position_max(), None);
let a = [-3, 0, 1, 5, -10];
assert_eq!(a.iter().position_max(), Some(3));
let a = [1, 1, -1, -1];
assert_eq!(a.iter().position_max(), Some(1));
sourcefn position_max_by_key<K, F>(self, key: F) -> Option<usize>
fn position_max_by_key<K, F>(self, key: F) -> Option<usize>
Return the position of the maximum element in the iterator, as determined by the specified function.
If several elements are equally maximum, the position of the last of them is returned.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().position_max_by_key(|x| x.abs()), None);
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(4));
let a = [1_i32, 1, -1, -1];
assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(3));
sourcefn position_max_by<F>(self, compare: F) -> Option<usize>
fn position_max_by<F>(self, compare: F) -> Option<usize>
Return the position of the maximum element in the iterator, as determined by the specified comparison function.
If several elements are equally maximum, the position of the last of them is returned.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), None);
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(3));
let a = [1_i32, 1, -1, -1];
assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(1));
sourcefn position_min(self) -> Option<usize>
fn position_min(self) -> Option<usize>
Return the position of the minimum element in the iterator.
If several elements are equally minimum, the position of the first of them is returned.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().position_min(), None);
let a = [-3, 0, 1, 5, -10];
assert_eq!(a.iter().position_min(), Some(4));
let a = [1, 1, -1, -1];
assert_eq!(a.iter().position_min(), Some(2));
sourcefn position_min_by_key<K, F>(self, key: F) -> Option<usize>
fn position_min_by_key<K, F>(self, key: F) -> Option<usize>
Return the position of the minimum element in the iterator, as determined by the specified function.
If several elements are equally minimum, the position of the first of them is returned.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().position_min_by_key(|x| x.abs()), None);
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(1));
let a = [1_i32, 1, -1, -1];
assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(0));
sourcefn position_min_by<F>(self, compare: F) -> Option<usize>
fn position_min_by<F>(self, compare: F) -> Option<usize>
Return the position of the minimum element in the iterator, as determined by the specified comparison function.
If several elements are equally minimum, the position of the first of them is returned.
§Examples
use itertools::Itertools;
let a: [i32; 0] = [];
assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), None);
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(4));
let a = [1_i32, 1, -1, -1];
assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(2));
sourcefn position_minmax(self) -> MinMaxResult<usize>
fn position_minmax(self) -> MinMaxResult<usize>
Return the positions of the minimum and maximum elements in the iterator.
The return type MinMaxResult
is an enum of three variants:
NoElements
if the iterator is empty.OneElement(xpos)
if the iterator has exactly one element.MinMax(xpos, ypos)
is returned otherwise, where the element atxpos
≤ the element atypos
. While the referenced elements themselves may be equal,xpos
cannot be equal toypos
.
On an iterator of length n
, position_minmax
does 1.5 * n
comparisons, and so is faster than calling position_min
and
position_max
separately which does 2 * n
comparisons.
For the minimum, if several elements are equally minimum, the position of the first of them is returned. For the maximum, if several elements are equally maximum, the position of the last of them is returned.
The elements can be floats but no particular result is guaranteed if an element is NaN.
§Examples
use itertools::Itertools;
use itertools::MinMaxResult::{NoElements, OneElement, MinMax};
let a: [i32; 0] = [];
assert_eq!(a.iter().position_minmax(), NoElements);
let a = [10];
assert_eq!(a.iter().position_minmax(), OneElement(0));
let a = [-3, 0, 1, 5, -10];
assert_eq!(a.iter().position_minmax(), MinMax(4, 3));
let a = [1, 1, -1, -1];
assert_eq!(a.iter().position_minmax(), MinMax(2, 1));
sourcefn position_minmax_by_key<K, F>(self, key: F) -> MinMaxResult<usize>
fn position_minmax_by_key<K, F>(self, key: F) -> MinMaxResult<usize>
Return the postions of the minimum and maximum elements of an iterator, as determined by the specified function.
The return value is a variant of MinMaxResult
like for
position_minmax
.
For the minimum, if several elements are equally minimum, the position of the first of them is returned. For the maximum, if several elements are equally maximum, the position of the last of them is returned.
The keys can be floats but no particular result is guaranteed if a key is NaN.
§Examples
use itertools::Itertools;
use itertools::MinMaxResult::{NoElements, OneElement, MinMax};
let a: [i32; 0] = [];
assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), NoElements);
let a = [10_i32];
assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), OneElement(0));
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(1, 4));
let a = [1_i32, 1, -1, -1];
assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(0, 3));
sourcefn position_minmax_by<F>(self, compare: F) -> MinMaxResult<usize>
fn position_minmax_by<F>(self, compare: F) -> MinMaxResult<usize>
Return the postions of the minimum and maximum elements of an iterator, as determined by the specified comparison function.
The return value is a variant of MinMaxResult
like for
position_minmax
.
For the minimum, if several elements are equally minimum, the position of the first of them is returned. For the maximum, if several elements are equally maximum, the position of the last of them is returned.
§Examples
use itertools::Itertools;
use itertools::MinMaxResult::{NoElements, OneElement, MinMax};
let a: [i32; 0] = [];
assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), NoElements);
let a = [10_i32];
assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), OneElement(0));
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(4, 3));
let a = [1_i32, 1, -1, -1];
assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(2, 1));
sourcefn exactly_one(self) -> Result<Self::Item, ExactlyOneError<Self>>where
Self: Sized,
fn exactly_one(self) -> Result<Self::Item, ExactlyOneError<Self>>where
Self: Sized,
If the iterator yields exactly one element, that element will be returned, otherwise an error will be returned containing an iterator that has the same output as the input iterator.
This provides an additional layer of validation over just calling Iterator::next()
.
If your assumption that there should only be one element yielded is false this provides
the opportunity to detect and handle that, preventing errors at a distance.
§Examples
use itertools::Itertools;
assert_eq!((0..10).filter(|&x| x == 2).exactly_one().unwrap(), 2);
assert!((0..10).filter(|&x| x > 1 && x < 4).exactly_one().unwrap_err().eq(2..4));
assert!((0..10).filter(|&x| x > 1 && x < 5).exactly_one().unwrap_err().eq(2..5));
assert!((0..10).filter(|&_| false).exactly_one().unwrap_err().eq(0..0));
sourcefn at_most_one(self) -> Result<Option<Self::Item>, ExactlyOneError<Self>>where
Self: Sized,
fn at_most_one(self) -> Result<Option<Self::Item>, ExactlyOneError<Self>>where
Self: Sized,
If the iterator yields no elements, Ok(None)
will be returned. If the iterator yields
exactly one element, that element will be returned, otherwise an error will be returned
containing an iterator that has the same output as the input iterator.
This provides an additional layer of validation over just calling Iterator::next()
.
If your assumption that there should be at most one element yielded is false this provides
the opportunity to detect and handle that, preventing errors at a distance.
§Examples
use itertools::Itertools;
assert_eq!((0..10).filter(|&x| x == 2).at_most_one().unwrap(), Some(2));
assert!((0..10).filter(|&x| x > 1 && x < 4).at_most_one().unwrap_err().eq(2..4));
assert!((0..10).filter(|&x| x > 1 && x < 5).at_most_one().unwrap_err().eq(2..5));
assert_eq!((0..10).filter(|&_| false).at_most_one().unwrap(), None);
sourcefn multipeek(self) -> MultiPeek<Self> ⓘwhere
Self: Sized,
fn multipeek(self) -> MultiPeek<Self> ⓘwhere
Self: Sized,
An iterator adaptor that allows the user to peek at multiple .next()
values without advancing the base iterator.
§Examples
use itertools::Itertools;
let mut iter = (0..10).multipeek();
assert_eq!(iter.peek(), Some(&0));
assert_eq!(iter.peek(), Some(&1));
assert_eq!(iter.peek(), Some(&2));
assert_eq!(iter.next(), Some(0));
assert_eq!(iter.peek(), Some(&1));
sourcefn counts(self) -> HashMap<Self::Item, usize>
fn counts(self) -> HashMap<Self::Item, usize>
Collect the items in this iterator and return a HashMap
which
contains each item that appears in the iterator and the number
of times it appears.
§Examples
let counts = [1, 1, 1, 3, 3, 5].into_iter().counts();
assert_eq!(counts[&1], 3);
assert_eq!(counts[&3], 2);
assert_eq!(counts[&5], 1);
assert_eq!(counts.get(&0), None);
sourcefn counts_by<K, F>(self, f: F) -> HashMap<K, usize>
fn counts_by<K, F>(self, f: F) -> HashMap<K, usize>
Collect the items in this iterator and return a HashMap
which
contains each item that appears in the iterator and the number
of times it appears,
determining identity using a keying function.
struct Character {
first_name: &'static str,
last_name: &'static str,
}
let characters =
vec![
Character { first_name: "Amy", last_name: "Pond" },
Character { first_name: "Amy", last_name: "Wong" },
Character { first_name: "Amy", last_name: "Santiago" },
Character { first_name: "James", last_name: "Bond" },
Character { first_name: "James", last_name: "Sullivan" },
Character { first_name: "James", last_name: "Norington" },
Character { first_name: "James", last_name: "Kirk" },
];
let first_name_frequency =
characters
.into_iter()
.counts_by(|c| c.first_name);
assert_eq!(first_name_frequency["Amy"], 3);
assert_eq!(first_name_frequency["James"], 4);
assert_eq!(first_name_frequency.contains_key("Asha"), false);
sourcefn multiunzip<FromI>(self) -> FromIwhere
Self: Sized + MultiUnzip<FromI>,
fn multiunzip<FromI>(self) -> FromIwhere
Self: Sized + MultiUnzip<FromI>,
Converts an iterator of tuples into a tuple of containers.
It consumes an entire iterator of n-ary tuples, producing n
collections, one for each
column.
This function is, in some sense, the opposite of multizip
.
use itertools::Itertools;
let inputs = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)];
let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = inputs
.into_iter()
.multiunzip();
assert_eq!(a, vec![1, 4, 7]);
assert_eq!(b, vec![2, 5, 8]);
assert_eq!(c, vec![3, 6, 9]);
sourcefn try_len(&self) -> Result<usize, (usize, Option<usize>)>
fn try_len(&self) -> Result<usize, (usize, Option<usize>)>
Returns the length of the iterator if one exists.
Otherwise return self.size_hint()
.
Fallible ExactSizeIterator::len
.
Inherits guarantees and restrictions from Iterator::size_hint
.
use itertools::Itertools;
assert_eq!([0; 10].iter().try_len(), Ok(10));
assert_eq!((10..15).try_len(), Ok(5));
assert_eq!((15..10).try_len(), Ok(0));
assert_eq!((10..).try_len(), Err((usize::MAX, None)));
assert_eq!((10..15).filter(|x| x % 2 == 0).try_len(), Err((0, Some(5))));