DoubleEndedIterator for ConsTuples (#853)MultiProduct fused and fixed on an empty iterator (#835, #834)iproduct! to return tuples for maxi one iterator too (#870)PutBack::put_back to return the old value (#880)repeat_call, Itertools::{foreach, step, map_results, fold_results} (#878)TakeWhileInclusive::new (#912)Itertools::{smallest_by, smallest_by_key, largest, largest_by, largest_by_key} (#654, #885)Itertools::tail (#899)DoubleEndedIterator for ProcessResults (#910)Debug for FormatWith (#931)Itertools::get (#891)Itertools::group_by (renamed chunk_by) (#866, #879)unfold (use std::iter::from_fn instead) (#871)GroupingMapBy (#873, #876)Fn bounds to FnMut in diff_with, Itertools::into_group_map_by (#886)Debug/Clone bounds for MapInto (#889)use_alloc feature (#887)Itertools::set_from (#888)README.md (#890)Cargo.toml (#894)Itertools::k_smallest on short unfused iterators (#900)Itertools::tree_fold1 (renamed tree_reduce) (#895)GroupingMap::fold_first (renamed reduce) (#902)Itertools::k_smallest(0) to consume the iterator, optimized Itertools::k_smallest(1) (#909)Combinations::nth (#914)MergeBy::fold (#920)CombinationsWithReplacement::nth (#923)FlattenOk::{fold, rfold} (#927)Powerset::nth (#924)assert_equal for iterators longer than i32::MAX (#932)must_use message of non-lazy KMergeBy and TupleCombinations (#939)CONTRIBUTING.md (#767)Itertools::[tuple_]combinations (#822)iterate (#842)Clone and Debug for Diff (#845)Debug for WithPosition (#859)Eq for MinMaxResult (#838)From<EitherOrBoth<A, B>> for Option<Either<A, B>> (#843)PeekingNext for RepeatN (#855)CoalesceBy lazy (#801)Filter[Map]Ok::next, Itertools::partition, Unique[By]::next[_back] (#818)Itertools::find_position (#837)Positions::next[_back] (#816)ZipLongest::fold (#854)Debug bounds for GroupingMapBy (#860)ExactlyOneError::fold (#826)Interleave[Shortest]::fold (#849)MultiPeek::fold (#820)PadUsing::[r]fold (#825)PeekNth::fold (#824)Positions::[r]fold (#813)PutBackN::fold (#823)RepeatN::[r]fold (#821)TakeWhileInclusive::fold (#851)ZipLongest::rfold (#848)clippy in CI (#740)rustdoc in CI (#840)take_while_inclusive consume iterator by value (#709)Clone bound to Unique (#777)Itertools::try_len (#723)sort_unstable (#796)GroupMap::fold_with (#778, #785)PeekNth::{peek_mut, peek_nth_mut} (#716)PeekNth::{next_if, next_if_eq} (#734)(Option<A>,Option<B>) to EitherOrBoth (#713)Either<A, B> to EitherOrBoth<A, B> (#715)ExactSizeIterator for Tuples (#761)ExactSizeIterator for (Circular)TupleWindows (#752)EitherOrBoth<T> a shorthand for EitherOrBoth<T, T> (#719)#[must_use] annotations on iterator adaptors (#794)Combinations lazy (#795)Intersperse(With) lazy (#797)Permutations lazy (#793)Product lazy (#800)TupleWindows lazy (#602)Combinations::{count, size_hint} (#729)CombinationsWithReplacement::{count, size_hint} (#737)Powerset::fold (#765)Powerset::count (#735)TupleCombinations::{count, size_hint} (#763)TupleCombinations::fold (#775)WhileSome::fold (#780)WithPosition::fold (#772)ZipLongest::fold (#774){min, max}_set* operations require alloc feature, instead of std (#760)tree_fold1 (#787)permutations (#724)multiunzip (#770)Permutations (#739, #748, #790)Merge/MergeBy/MergeJoinBy implementations (#736)Permutations::size_hint (#739)rustfmt in CI (#751)cargo hack to check MSRV (#754)Itertools::merge_join_by also accept functions returning bool (#704)PeekingNext transitively over mutable references (#643)with_position to yield (Position, Item) instead of Position<Item> (#699)Itertools::take_while_inclusive (#616)PeekingNext for PeekingTakeWhile (#644)EitherOrBoth::{just_left, just_right, into_left, into_right, as_deref, as_deref_mut, left_or_insert, right_or_insert, left_or_insert_with, right_or_insert_with, insert_left, insert_right, insert_both} (#629)Clone for CircularTupleWindows (#686)Clone for Chunks (#683)Itertools::process_results (#680)Cell instead of RefCell in Format and FormatWith (#608)Itertools::max_set_by_key (#692)Cargo.toml (#672)equal with Iterator::eq (#591)EitherOrBoth::or and EitherOrBoth::or_else (#593)min_set, max_set et al. (#613, #323)either/use_std (#628)Itertools::multiunzip (#362, #565)intersperse and intersperse_with free functions (#555)Itertools::sorted_by_cached_key (#424, #575)ProcessResults::fold (#563)DuplicatesBy::size_hint (#552)Debug impls (#573)fold1 (use reduce instead) (#580)HomogenousTuple, into_group_map, into_group_map_by, MultiPeek::peek) (#543 et al.)Itertools::contains (#514)Itertools::counts_by (#515)Itertools::partition_result (#511)Itertools::all_unique (#241)Itertools::duplicates and Itertools::duplicates_by (#502)chain! (#525)Itertools::at_most_one (#523)Itertools::flatten_ok (#527)EitherOrBoth::or_default (#583)Itertools::find_or_last and Itertools::find_or_first (#535)FusedIterator for FilterOk, FilterMapOk, InterleaveShortest, KMergeBy, MergeBy, PadUsing, Positions, Product , RcIter, TupleWindows, Unique, UniqueBy, Update, WhileSome, Combinations, CombinationsWithReplacement, Powerset, RepeatN, and WithPosition (#550)FusedIterator for Interleave, IntersperseWith, and ZipLongest (#548)Itertools::powerset (#335)Itertools::sorted_unstable, Itertools::sorted_unstable_by, and Itertools::sorted_unstable_by_key (#494)Error for ExactlyOneError (#484)Itertools::fold_while (#476)use_alloc feature for users who have alloc, but not std (#474)Itertools::k_smallest (#473)Itertools::into_grouping_map and GroupingMap (#465)Itertools::into_grouping_map_by and GroupingMapBy (#465)Itertools::counts (#468)DoubleEndedIterator for Unique (#442)DoubleEndedIterator for UniqueBy (#442)DoubleEndedIterator for Zip (#346)Itertools::multipeek (#435)Itertools::dedup_with_count and DedupWithCount (#423)Itertools::dedup_by_with_count and DedupByWithCount (#423)Itertools::intersperse_with and IntersperseWith (#381)Itertools::filter_ok and FilterOk (#377)Itertools::filter_map_ok and FilterMapOk (#377)Itertools::fold_results, use Itertools::fold_ok instead (#377)Itertools::map_results, use Itertools::map_ok instead (#377)FoldResults, use FoldOk instead (#377)MapResults, use MapOk instead (#377)Itertools::circular_tuple_windows and CircularTupleWindows (#350)peek_nth and PeekNth (#303)MergeJoinBy::size_hint (#385)derive(Clone) where possible (#382)try_collect method (#394)HomogeneousTuple trait (#389)combinations(0) and combinations_with_replacement(0) (#383)ParitalEq to the Item of DedupBy (#397)PutBack adaptor and on the MergeJoinBy iterator (#372)position_* methods (#412)Hash for EitherOrBoth (#417)slice::iter instead of into_iter to avoid future breakage (#378, by @LukasKalbertodt)Added a .exactly_one() iterator method that, on success, extracts the single value of an iterator ; by @Xaeroxe
Added combinatory iterator adaptors:
[0, 1, 2].iter().permutations(2) yields
[ vec![0, 1], vec![0, 2], vec![1, 0], vec![1, 2], vec![2, 0], vec![2, 1], ]
; by @tobz1000
.combinations_with_replacement(k):
[0, 1, 2].iter().combinations_with_replacement(2) yields
[ vec![0, 0], vec![0, 1], vec![0, 2], vec![1, 1], vec![1, 2], vec![2, 2], ]
; by @tommilligan
For reference, these methods join the already existing .combinations(k):
[0, 1, 2].iter().combinations(2) yields
[ vec![0, 1], vec![0, 2], vec![1, 2], ]
Improved the performance of .fold()-based internal iteration for the .intersperse() iterator ; by @jswrenn
Added .dedup_by(), .merge_by() and .kmerge_by() adaptors that work like .dedup(), .merge() and .kmerge(), but taking an additional custom comparison closure parameter. ; by @phimuemue
Improved the performance of .all_equal() ; by @fyrchik
Loosened the bounds on .partition_map() to take just a FnMut closure rather than a Fn closure, and made its implementation use internal iteration for better performance ; by @danielhenrymantilla
Added convenience methods to EitherOrBoth elements yielded from the .zip_longest() iterator adaptor ; by @Avi-D-coder
Added .sum1() and .product1() iterator methods that respectively try to return the sum and the product of the elements of an iterator when it is not empty, otherwise they return None ; by @Emerentius
.map_into() for conversions using Into by @vornerItertools docs by @JohnHeitmann.sorted_by_by_key() is now an iterator, not a Vec.izip!(x, y) macro with exactly two arguments is now the usual Iterator::zip..flatten() in favour of std's .flatten().foreach() in favour of std's .for_each().step() in favour of std's .step_by()repeat_call in favour of std's repeat_with.fold_while() in favour of std's .try_fold()EitherOrBoth, making it more similar to Option and Either by @jethrogbFoldWhile type now implements Eq and PartialEq by @jturner314.tree_fold1() which is like .fold1() except items are combined in a tree structure (see its docs). By @scottmcmDebug impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy, ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee, ZipLongest, ZipEq, Zip..into_group_map() -> HashMap<K, Vec<V>> which turns an iterator of (K, V) elements into such a hash table, where values are grouped by key. By @tobz1000flatten for the .flatten() adaptor. NOTE: recent Rust nightlies have Iterator::flatten and thus a clash with our flatten adaptor. One workaround is to use the itertools flatten free function..multi_cartesian_product() which is an n-ary product iterator by @tobz1000.sorted_by_key() by @Xion.count() for .unique() and .unique_by().multipeek() now implements PeekingNext, by @nicopap..update() by @lucasem; this adaptor is used to modify an element before passing it on in an iterator chain..collect_tuple() by @matklad; it makes a tuple out of the iterator's elements if the number of them matches exactly.fold and collect for .map_results() which means it reuses the code of the standard .map() for these methods..merge_join_by by @srijs; a heterogeneous merge join for two ordered sequences.must_use reminder that the standard library adaptors do, by @matematikaedit and @bluss “iterator adaptors are lazy and do nothing unless consumed”.izip!() by @krdlnizip!() is now a wrapper for repeated regular .zip() and a single .map(). This means it optimizes as well as the standard library .zip() it uses. Note: multizip and izip!() are now different! The former has a named type but the latter optimizes better..unique()no_std support, which is opt-in!izip!() or .format() or .merge(), but not those that use collections.group_by's PartialEq by @Phlosioneer and repeat_call's FnMut.Zip::new — use izip!() or multizip().cartesian_product()'s fold (which only was visible for unfused iterators).fold implementations for .cartesian_product() and cons_tuples(), which improves their performance in fold, foreach, and iterator consumers derived from them..positions(predicate) by @tmccombsprocess_results which can “lift” a function of the regular values of an iterator so that it can process the Ok values from an iterator of Results instead, by @shepmaster.concat() which combines all iterator elements into a single collection using the Extend trait, by @srijsinterleave_shortest size hints..all_equal() by @phimuemue.flatten() does not implement double ended iteration anymore.fold_while() uses &mut self and returns FoldWhile<T>, for composability #168.foreach() and .fold1() use self, like .fold() does..combinations(0) now produces a single empty vector. #174.kmerge_by() (and corresponding free function).kmerge() and .minmax() to PartialOrd..reset_peek().peeking_take_while() and its trait PeekingNext..with_position()VecDeque..map_results()Debugrepeat_n. RepeatN::new is now deprecated.iterate, that takes a seed and a closure..fold() for flatten and put back. .foreach() now uses fold on the iterator, to pick up any iterator specific loop implementation..combinations(n) asserts up front that n != 0, instead of running into an error on the second iterator element..tuples::<T>() that iterates by two, three or four elements at a time (where T is a tuple type)..tuple_windows::<T>() that iterates using a window of the two, three or four most recent elements..next_tuple::<T>() method, that picks the next two, three or four elements in one go..interleave() now has an accurate size hint.combinations is now tuple_combinationscombinations_n to combinationsgroup_by_lazy, chunks_lazy to group_by, chunksUnfold::new to unfold()RepeatCall::new to repeat_call()Zip::new to multizipPutBack::new, PutBackN::new to put_back, put_back_nPutBack::with_value is now a builder setter, not a constructorMultiPeek::new, .multipeek() to multipeek()format to format_with and format_default to format.into_rc() to rciterPartition enum is now Eitheritertools::structs but also reexported to the top level, for backwards compatibilityitertools::free will be removed in the next versionZipSlices, use .zip() instead.enumerate_from(), ZipTrusted, due to being unstable.mend_slices(), moved to crate oddsoddslinspace(), moved to crate itertools-num.sort_by(), use .sorted_by().is_empty_hint(), use .size_hint().dropn(), use .dropping().map_fn(), use .map().slice(), use .take() / .skip()miscnew constructors on iterator structs, use Itertools trait or free functions insteaditertools::size_hint is now privateformat and format_with helpers now panic if you try to format them more than once.repeat_call is not double ended anymorecons_tuplesEither from the either crate. Either<L, R> is an iterator when L, R are.MinMaxResult now implements Copy and Clonetuple_combinations supports 1-4 tuples of combinations (previously just 2).minmax_by()itertools::free::cloneditertools::free::rciter.step(n) slightly to take advantage of specialized Fuse better..enumerate_from() will be removed imminently since it's using a deprecated libstd trait..kmerge() that caused it to often produce the wrong order #134interleave_shortest adaptor's size hint (it is now computed exactly when possible).itertools::free was removed by mistake and now it is added back again.itertools::free::{interleave, merge}.minmax() and .minmax_by_key(), iterator methods for finding both minimum and maximum in one scan..format_default(), a simpler version of .format() (lazy formatting for iterators)..zip_eq(), an adaptor like .zip() except it ensures iterators of inequal length don't pass silently (instead it panics)..fold_while(), an iterator method that is a fold that can short-circuit..partition_map(), an iterator method that can separate elements into two collections..get() for Stride{,Mut} and .get_mut() for StrideMut.kmerge().kmerge().islice() with ranges a..b where a > b.Clone, Debug for Linspacediff_with() that compares two iterators.combinations_n(), an n-ary combinations iteratorPutBack::with_value and PutBack::into_parts..sorted()itertools::free with free function variants of common iterator adaptors and methods. For example enumerate(iterable), rev(iterable), and so on..flatten()ZipSlices with itselfiproduct!() as a single expression; this allows temporary values in its arguments..fold_options().dropping() to take advantage of .nth().merge(), .unique() and .dedup() now perform better due to not using function pointersenumerate() and rev().merge() and .merge_by() renamed and changedMerge::new removed.merge_by() now takes a closure that returns bool..dedup() changed.mend_slices() changed.unique() changedtimes(), struct Times: use a range insteadicompr!()FnMap and method .fn_map(): use .map_fn().interleave_shortest() is no longer guaranteed to act like fused.sort_by() to .sorted_by(). Old name is deprecated..merge()'s ordering function slightly.chunks(), similar to (and based on) .group_by_lazy().ZipSlices, a fast zip for slicesDebug impl for Format, it will have different use later.group_by_lazy().group_by_lazy(), a possibly nonallocating group by.format(), a nonallocating formatting helper for iteratorsRandomAccessIterator since it has been deprecated in Rust.Unfold from Rust.unique(), .unique_by().sort_by().while_some().interleave_shortest().pad_using()assert_equal function.combinations() size_hint.RepeatCallPutBackN.combinations()itertools::partition, partition a sequence in place based on a predicate.icompr!() with no replacement..map_fn() replaces deprecated .fn_map()..take_while_ref() by-ref adaptor.coalesce() adaptor.mend_slices() adaptor.dropping_back() method.fold1() method.is_empty_hint() method