Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1 | #![warn(missing_docs)] |
| 2 | #![crate_name="itertools"] |
| 3 | #![cfg_attr(not(feature = "use_std"), no_std)] |
| 4 | |
| 5 | //! Extra iterator adaptors, functions and macros. |
| 6 | //! |
| 7 | //! To extend [`Iterator`] with methods in this crate, import |
| 8 | //! the [`Itertools` trait](./trait.Itertools.html): |
| 9 | //! |
| 10 | //! ``` |
| 11 | //! use itertools::Itertools; |
| 12 | //! ``` |
| 13 | //! |
| 14 | //! Now, new methods like [`interleave`](./trait.Itertools.html#method.interleave) |
| 15 | //! are available on all iterators: |
| 16 | //! |
| 17 | //! ``` |
| 18 | //! use itertools::Itertools; |
| 19 | //! |
| 20 | //! let it = (1..3).interleave(vec![-1, -2]); |
| 21 | //! itertools::assert_equal(it, vec![1, -1, 2, -2]); |
| 22 | //! ``` |
| 23 | //! |
| 24 | //! Most iterator methods are also provided as functions (with the benefit |
| 25 | //! that they convert parameters using [`IntoIterator`]): |
| 26 | //! |
| 27 | //! ``` |
| 28 | //! use itertools::interleave; |
| 29 | //! |
| 30 | //! for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { |
| 31 | //! /* loop body */ |
| 32 | //! } |
| 33 | //! ``` |
| 34 | //! |
| 35 | //! ## Crate Features |
| 36 | //! |
| 37 | //! - `use_std` |
| 38 | //! - Enabled by default. |
| 39 | //! - Disable to compile itertools using `#![no_std]`. This disables |
| 40 | //! any items that depend on collections (like `group_by`, `unique`, |
| 41 | //! `kmerge`, `join` and many more). |
| 42 | //! |
| 43 | //! ## Rust Version |
| 44 | //! |
| 45 | //! This version of itertools requires Rust 1.32 or later. |
| 46 | //! |
| 47 | //! [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html |
| 48 | #![doc(html_root_url="https://docs.rs/itertools/0.8/")] |
| 49 | |
| 50 | #[cfg(not(feature = "use_std"))] |
| 51 | extern crate core as std; |
| 52 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 53 | #[cfg(feature = "use_alloc")] |
| 54 | extern crate alloc; |
| 55 | |
| 56 | #[cfg(feature = "use_alloc")] |
| 57 | use alloc::{ |
| 58 | string::String, |
| 59 | vec::Vec, |
| 60 | }; |
| 61 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 62 | pub use either::Either; |
| 63 | |
| 64 | #[cfg(feature = "use_std")] |
| 65 | use std::collections::HashMap; |
| 66 | use std::iter::{IntoIterator, once}; |
| 67 | use std::cmp::Ordering; |
| 68 | use std::fmt; |
| 69 | #[cfg(feature = "use_std")] |
| 70 | use std::hash::Hash; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 71 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 72 | use std::fmt::Write; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 73 | #[cfg(feature = "use_alloc")] |
| 74 | type VecIntoIter<T> = alloc::vec::IntoIter<T>; |
| 75 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 76 | use std::iter::FromIterator; |
| 77 | |
| 78 | #[macro_use] |
| 79 | mod impl_macros; |
| 80 | |
| 81 | // for compatibility with no std and macros |
| 82 | #[doc(hidden)] |
| 83 | pub use std::iter as __std_iter; |
| 84 | |
| 85 | /// The concrete iterator types. |
| 86 | pub mod structs { |
| 87 | pub use crate::adaptors::{ |
| 88 | Dedup, |
| 89 | DedupBy, |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 90 | DedupWithCount, |
| 91 | DedupByWithCount, |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 92 | Interleave, |
| 93 | InterleaveShortest, |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 94 | FilterMapOk, |
| 95 | FilterOk, |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 96 | Product, |
| 97 | PutBack, |
| 98 | Batching, |
| 99 | MapInto, |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 100 | MapOk, |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 101 | Merge, |
| 102 | MergeBy, |
| 103 | TakeWhileRef, |
| 104 | WhileSome, |
| 105 | Coalesce, |
| 106 | TupleCombinations, |
| 107 | Positions, |
| 108 | Update, |
| 109 | }; |
| 110 | #[allow(deprecated)] |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 111 | pub use crate::adaptors::{MapResults, Step}; |
| 112 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 113 | pub use crate::adaptors::MultiProduct; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 114 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 115 | pub use crate::combinations::Combinations; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 116 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 117 | pub use crate::combinations_with_replacement::CombinationsWithReplacement; |
| 118 | pub use crate::cons_tuples_impl::ConsTuples; |
| 119 | pub use crate::exactly_one_err::ExactlyOneError; |
| 120 | pub use crate::format::{Format, FormatWith}; |
| 121 | #[cfg(feature = "use_std")] |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 122 | pub use crate::grouping_map::{GroupingMap, GroupingMapBy}; |
| 123 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 124 | pub use crate::groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups}; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 125 | pub use crate::intersperse::{Intersperse, IntersperseWith}; |
| 126 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 127 | pub use crate::kmerge_impl::{KMerge, KMergeBy}; |
| 128 | pub use crate::merge_join::MergeJoinBy; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 129 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 130 | pub use crate::multipeek_impl::MultiPeek; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 131 | #[cfg(feature = "use_alloc")] |
| 132 | pub use crate::peek_nth::PeekNth; |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 133 | pub use crate::pad_tail::PadUsing; |
| 134 | pub use crate::peeking_take_while::PeekingTakeWhile; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 135 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 136 | pub use crate::permutations::Permutations; |
| 137 | pub use crate::process_results_impl::ProcessResults; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 138 | #[cfg(feature = "use_alloc")] |
| 139 | pub use crate::powerset::Powerset; |
| 140 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 141 | pub use crate::put_back_n_impl::PutBackN; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 142 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 143 | pub use crate::rciter_impl::RcIter; |
| 144 | pub use crate::repeatn::RepeatN; |
| 145 | #[allow(deprecated)] |
| 146 | pub use crate::sources::{RepeatCall, Unfold, Iterate}; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 147 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 148 | pub use crate::tee::Tee; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 149 | pub use crate::tuple_impl::{TupleBuffer, TupleWindows, CircularTupleWindows, Tuples}; |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 150 | #[cfg(feature = "use_std")] |
| 151 | pub use crate::unique_impl::{Unique, UniqueBy}; |
| 152 | pub use crate::with_position::WithPosition; |
| 153 | pub use crate::zip_eq_impl::ZipEq; |
| 154 | pub use crate::zip_longest::ZipLongest; |
| 155 | pub use crate::ziptuple::Zip; |
| 156 | } |
| 157 | |
| 158 | /// Traits helpful for using certain `Itertools` methods in generic contexts. |
| 159 | pub mod traits { |
| 160 | pub use crate::tuple_impl::HomogeneousTuple; |
| 161 | } |
| 162 | |
| 163 | #[allow(deprecated)] |
| 164 | pub use crate::structs::*; |
| 165 | pub use crate::concat_impl::concat; |
| 166 | pub use crate::cons_tuples_impl::cons_tuples; |
| 167 | pub use crate::diff::diff_with; |
| 168 | pub use crate::diff::Diff; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 169 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 170 | pub use crate::kmerge_impl::{kmerge_by}; |
| 171 | pub use crate::minmax::MinMaxResult; |
| 172 | pub use crate::peeking_take_while::PeekingNext; |
| 173 | pub use crate::process_results_impl::process_results; |
| 174 | pub use crate::repeatn::repeat_n; |
| 175 | #[allow(deprecated)] |
| 176 | pub use crate::sources::{repeat_call, unfold, iterate}; |
| 177 | pub use crate::with_position::Position; |
| 178 | pub use crate::ziptuple::multizip; |
| 179 | mod adaptors; |
| 180 | mod either_or_both; |
| 181 | pub use crate::either_or_both::EitherOrBoth; |
| 182 | #[doc(hidden)] |
| 183 | pub mod free; |
| 184 | #[doc(inline)] |
| 185 | pub use crate::free::*; |
| 186 | mod concat_impl; |
| 187 | mod cons_tuples_impl; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 188 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 189 | mod combinations; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 190 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 191 | mod combinations_with_replacement; |
| 192 | mod exactly_one_err; |
| 193 | mod diff; |
| 194 | mod format; |
| 195 | #[cfg(feature = "use_std")] |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 196 | mod grouping_map; |
| 197 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 198 | mod group_map; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 199 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 200 | mod groupbylazy; |
| 201 | mod intersperse; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 202 | #[cfg(feature = "use_alloc")] |
| 203 | mod k_smallest; |
| 204 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 205 | mod kmerge_impl; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 206 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 207 | mod lazy_buffer; |
| 208 | mod merge_join; |
| 209 | mod minmax; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 210 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 211 | mod multipeek_impl; |
| 212 | mod pad_tail; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 213 | #[cfg(feature = "use_alloc")] |
| 214 | mod peek_nth; |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 215 | mod peeking_take_while; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 216 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 217 | mod permutations; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 218 | #[cfg(feature = "use_alloc")] |
| 219 | mod powerset; |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 220 | mod process_results_impl; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 221 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 222 | mod put_back_n_impl; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 223 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 224 | mod rciter_impl; |
| 225 | mod repeatn; |
| 226 | mod size_hint; |
| 227 | mod sources; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 228 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 229 | mod tee; |
| 230 | mod tuple_impl; |
| 231 | #[cfg(feature = "use_std")] |
| 232 | mod unique_impl; |
| 233 | mod with_position; |
| 234 | mod zip_eq_impl; |
| 235 | mod zip_longest; |
| 236 | mod ziptuple; |
| 237 | |
| 238 | #[macro_export] |
| 239 | /// Create an iterator over the “cartesian product” of iterators. |
| 240 | /// |
| 241 | /// Iterator element type is like `(A, B, ..., E)` if formed |
| 242 | /// from iterators `(I, J, ..., M)` with element types `I::Item = A`, `J::Item = B`, etc. |
| 243 | /// |
| 244 | /// ``` |
| 245 | /// # use itertools::iproduct; |
| 246 | /// # |
| 247 | /// # fn main() { |
| 248 | /// // Iterate over the coordinates of a 4 x 4 x 4 grid |
| 249 | /// // from (0, 0, 0), (0, 0, 1), .., (0, 1, 0), (0, 1, 1), .. etc until (3, 3, 3) |
| 250 | /// for (i, j, k) in iproduct!(0..4, 0..4, 0..4) { |
| 251 | /// // .. |
| 252 | /// } |
| 253 | /// # } |
| 254 | /// ``` |
| 255 | macro_rules! iproduct { |
| 256 | (@flatten $I:expr,) => ( |
| 257 | $I |
| 258 | ); |
| 259 | (@flatten $I:expr, $J:expr, $($K:expr,)*) => ( |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 260 | $crate::iproduct!(@flatten $crate::cons_tuples($crate::iproduct!($I, $J)), $($K,)*) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 261 | ); |
| 262 | ($I:expr) => ( |
| 263 | $crate::__std_iter::IntoIterator::into_iter($I) |
| 264 | ); |
| 265 | ($I:expr, $J:expr) => ( |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 266 | $crate::Itertools::cartesian_product($crate::iproduct!($I), $crate::iproduct!($J)) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 267 | ); |
| 268 | ($I:expr, $J:expr, $($K:expr),+) => ( |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 269 | $crate::iproduct!(@flatten $crate::iproduct!($I, $J), $($K,)+) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 270 | ); |
| 271 | } |
| 272 | |
| 273 | #[macro_export] |
| 274 | /// Create an iterator running multiple iterators in lockstep. |
| 275 | /// |
| 276 | /// The `izip!` iterator yields elements until any subiterator |
| 277 | /// returns `None`. |
| 278 | /// |
| 279 | /// This is a version of the standard ``.zip()`` that's supporting more than |
| 280 | /// two iterators. The iterator element type is a tuple with one element |
| 281 | /// from each of the input iterators. Just like ``.zip()``, the iteration stops |
| 282 | /// when the shortest of the inputs reaches its end. |
| 283 | /// |
| 284 | /// **Note:** The result of this macro is in the general case an iterator |
| 285 | /// composed of repeated `.zip()` and a `.map()`; it has an anonymous type. |
| 286 | /// The special cases of one and two arguments produce the equivalent of |
| 287 | /// `$a.into_iter()` and `$a.into_iter().zip($b)` respectively. |
| 288 | /// |
| 289 | /// Prefer this macro `izip!()` over [`multizip`] for the performance benefits |
| 290 | /// of using the standard library `.zip()`. |
| 291 | /// |
| 292 | /// [`multizip`]: fn.multizip.html |
| 293 | /// |
| 294 | /// ``` |
| 295 | /// # use itertools::izip; |
| 296 | /// # |
| 297 | /// # fn main() { |
| 298 | /// |
| 299 | /// // iterate over three sequences side-by-side |
| 300 | /// let mut results = [0, 0, 0, 0]; |
| 301 | /// let inputs = [3, 7, 9, 6]; |
| 302 | /// |
| 303 | /// for (r, index, input) in izip!(&mut results, 0..10, &inputs) { |
| 304 | /// *r = index * 10 + input; |
| 305 | /// } |
| 306 | /// |
| 307 | /// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); |
| 308 | /// # } |
| 309 | /// ``` |
| 310 | macro_rules! izip { |
| 311 | // @closure creates a tuple-flattening closure for .map() call. usage: |
| 312 | // @closure partial_pattern => partial_tuple , rest , of , iterators |
| 313 | // eg. izip!( @closure ((a, b), c) => (a, b, c) , dd , ee ) |
| 314 | ( @closure $p:pat => $tup:expr ) => { |
| 315 | |$p| $tup |
| 316 | }; |
| 317 | |
| 318 | // The "b" identifier is a different identifier on each recursion level thanks to hygiene. |
| 319 | ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 320 | $crate::izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 321 | }; |
| 322 | |
| 323 | // unary |
| 324 | ($first:expr $(,)*) => { |
| 325 | $crate::__std_iter::IntoIterator::into_iter($first) |
| 326 | }; |
| 327 | |
| 328 | // binary |
| 329 | ($first:expr, $second:expr $(,)*) => { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 330 | $crate::izip!($first) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 331 | .zip($second) |
| 332 | }; |
| 333 | |
| 334 | // n-ary where n > 2 |
| 335 | ( $first:expr $( , $rest:expr )* $(,)* ) => { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 336 | $crate::izip!($first) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 337 | $( |
| 338 | .zip($rest) |
| 339 | )* |
| 340 | .map( |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 341 | $crate::izip!(@closure a => (a) $( , $rest )*) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 342 | ) |
| 343 | }; |
| 344 | } |
| 345 | |
| 346 | /// An [`Iterator`] blanket implementation that provides extra adaptors and |
| 347 | /// methods. |
| 348 | /// |
| 349 | /// This trait defines a number of methods. They are divided into two groups: |
| 350 | /// |
| 351 | /// * *Adaptors* take an iterator and parameter as input, and return |
| 352 | /// a new iterator value. These are listed first in the trait. An example |
| 353 | /// of an adaptor is [`.interleave()`](#method.interleave) |
| 354 | /// |
| 355 | /// * *Regular methods* are those that don't return iterators and instead |
| 356 | /// return a regular value of some other kind. |
| 357 | /// [`.next_tuple()`](#method.next_tuple) is an example and the first regular |
| 358 | /// method in the list. |
| 359 | /// |
| 360 | /// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html |
| 361 | pub trait Itertools : Iterator { |
| 362 | // adaptors |
| 363 | |
| 364 | /// Alternate elements from two iterators until both have run out. |
| 365 | /// |
| 366 | /// Iterator element type is `Self::Item`. |
| 367 | /// |
| 368 | /// This iterator is *fused*. |
| 369 | /// |
| 370 | /// ``` |
| 371 | /// use itertools::Itertools; |
| 372 | /// |
| 373 | /// let it = (1..7).interleave(vec![-1, -2]); |
| 374 | /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]); |
| 375 | /// ``` |
| 376 | fn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter> |
| 377 | where J: IntoIterator<Item = Self::Item>, |
| 378 | Self: Sized |
| 379 | { |
| 380 | interleave(self, other) |
| 381 | } |
| 382 | |
| 383 | /// Alternate elements from two iterators until at least one of them has run |
| 384 | /// out. |
| 385 | /// |
| 386 | /// Iterator element type is `Self::Item`. |
| 387 | /// |
| 388 | /// ``` |
| 389 | /// use itertools::Itertools; |
| 390 | /// |
| 391 | /// let it = (1..7).interleave_shortest(vec![-1, -2]); |
| 392 | /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3]); |
| 393 | /// ``` |
| 394 | fn interleave_shortest<J>(self, other: J) -> InterleaveShortest<Self, J::IntoIter> |
| 395 | where J: IntoIterator<Item = Self::Item>, |
| 396 | Self: Sized |
| 397 | { |
| 398 | adaptors::interleave_shortest(self, other.into_iter()) |
| 399 | } |
| 400 | |
| 401 | /// An iterator adaptor to insert a particular value |
| 402 | /// between each element of the adapted iterator. |
| 403 | /// |
| 404 | /// Iterator element type is `Self::Item`. |
| 405 | /// |
| 406 | /// This iterator is *fused*. |
| 407 | /// |
| 408 | /// ``` |
| 409 | /// use itertools::Itertools; |
| 410 | /// |
| 411 | /// itertools::assert_equal((0..3).intersperse(8), vec![0, 8, 1, 8, 2]); |
| 412 | /// ``` |
| 413 | fn intersperse(self, element: Self::Item) -> Intersperse<Self> |
| 414 | where Self: Sized, |
| 415 | Self::Item: Clone |
| 416 | { |
| 417 | intersperse::intersperse(self, element) |
| 418 | } |
| 419 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 420 | /// An iterator adaptor to insert a particular value created by a function |
| 421 | /// between each element of the adapted iterator. |
| 422 | /// |
| 423 | /// Iterator element type is `Self::Item`. |
| 424 | /// |
| 425 | /// This iterator is *fused*. |
| 426 | /// |
| 427 | /// ``` |
| 428 | /// use itertools::Itertools; |
| 429 | /// |
| 430 | /// let mut i = 10; |
| 431 | /// itertools::assert_equal((0..3).intersperse_with(|| { i -= 1; i }), vec![0, 9, 1, 8, 2]); |
| 432 | /// assert_eq!(i, 8); |
| 433 | /// ``` |
| 434 | fn intersperse_with<F>(self, element: F) -> IntersperseWith<Self, F> |
| 435 | where Self: Sized, |
| 436 | F: FnMut() -> Self::Item |
| 437 | { |
| 438 | intersperse::intersperse_with(self, element) |
| 439 | } |
| 440 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 441 | /// Create an iterator which iterates over both this and the specified |
| 442 | /// iterator simultaneously, yielding pairs of two optional elements. |
| 443 | /// |
| 444 | /// This iterator is *fused*. |
| 445 | /// |
| 446 | /// As long as neither input iterator is exhausted yet, it yields two values |
| 447 | /// via `EitherOrBoth::Both`. |
| 448 | /// |
| 449 | /// When the parameter iterator is exhausted, it only yields a value from the |
| 450 | /// `self` iterator via `EitherOrBoth::Left`. |
| 451 | /// |
| 452 | /// When the `self` iterator is exhausted, it only yields a value from the |
| 453 | /// parameter iterator via `EitherOrBoth::Right`. |
| 454 | /// |
| 455 | /// When both iterators return `None`, all further invocations of `.next()` |
| 456 | /// will return `None`. |
| 457 | /// |
| 458 | /// Iterator element type is |
| 459 | /// [`EitherOrBoth<Self::Item, J::Item>`](enum.EitherOrBoth.html). |
| 460 | /// |
| 461 | /// ```rust |
| 462 | /// use itertools::EitherOrBoth::{Both, Right}; |
| 463 | /// use itertools::Itertools; |
| 464 | /// let it = (0..1).zip_longest(1..3); |
| 465 | /// itertools::assert_equal(it, vec![Both(0, 1), Right(2)]); |
| 466 | /// ``` |
| 467 | #[inline] |
| 468 | fn zip_longest<J>(self, other: J) -> ZipLongest<Self, J::IntoIter> |
| 469 | where J: IntoIterator, |
| 470 | Self: Sized |
| 471 | { |
| 472 | zip_longest::zip_longest(self, other.into_iter()) |
| 473 | } |
| 474 | |
| 475 | /// Create an iterator which iterates over both this and the specified |
| 476 | /// iterator simultaneously, yielding pairs of elements. |
| 477 | /// |
| 478 | /// **Panics** if the iterators reach an end and they are not of equal |
| 479 | /// lengths. |
| 480 | #[inline] |
| 481 | fn zip_eq<J>(self, other: J) -> ZipEq<Self, J::IntoIter> |
| 482 | where J: IntoIterator, |
| 483 | Self: Sized |
| 484 | { |
| 485 | zip_eq(self, other) |
| 486 | } |
| 487 | |
| 488 | /// A “meta iterator adaptor”. Its closure receives a reference to the |
| 489 | /// iterator and may pick off as many elements as it likes, to produce the |
| 490 | /// next iterator element. |
| 491 | /// |
| 492 | /// Iterator element type is `B`. |
| 493 | /// |
| 494 | /// ``` |
| 495 | /// use itertools::Itertools; |
| 496 | /// |
| 497 | /// // An adaptor that gathers elements in pairs |
| 498 | /// let pit = (0..4).batching(|it| { |
| 499 | /// match it.next() { |
| 500 | /// None => None, |
| 501 | /// Some(x) => match it.next() { |
| 502 | /// None => None, |
| 503 | /// Some(y) => Some((x, y)), |
| 504 | /// } |
| 505 | /// } |
| 506 | /// }); |
| 507 | /// |
| 508 | /// itertools::assert_equal(pit, vec![(0, 1), (2, 3)]); |
| 509 | /// ``` |
| 510 | /// |
| 511 | fn batching<B, F>(self, f: F) -> Batching<Self, F> |
| 512 | where F: FnMut(&mut Self) -> Option<B>, |
| 513 | Self: Sized |
| 514 | { |
| 515 | adaptors::batching(self, f) |
| 516 | } |
| 517 | |
| 518 | /// Return an *iterable* that can group iterator elements. |
| 519 | /// Consecutive elements that map to the same key (“runs”), are assigned |
| 520 | /// to the same group. |
| 521 | /// |
| 522 | /// `GroupBy` is the storage for the lazy grouping operation. |
| 523 | /// |
| 524 | /// If the groups are consumed in order, or if each group's iterator is |
| 525 | /// dropped without keeping it around, then `GroupBy` uses no |
| 526 | /// allocations. It needs allocations only if several group iterators |
| 527 | /// are alive at the same time. |
| 528 | /// |
| 529 | /// This type implements `IntoIterator` (it is **not** an iterator |
| 530 | /// itself), because the group iterators need to borrow from this |
| 531 | /// value. It should be stored in a local variable or temporary and |
| 532 | /// iterated. |
| 533 | /// |
| 534 | /// Iterator element type is `(K, Group)`: the group's key and the |
| 535 | /// group iterator. |
| 536 | /// |
| 537 | /// ``` |
| 538 | /// use itertools::Itertools; |
| 539 | /// |
| 540 | /// // group data into runs of larger than zero or not. |
| 541 | /// let data = vec![1, 3, -2, -2, 1, 0, 1, 2]; |
| 542 | /// // groups: |---->|------>|--------->| |
| 543 | /// |
| 544 | /// // Note: The `&` is significant here, `GroupBy` is iterable |
| 545 | /// // only by reference. You can also call `.into_iter()` explicitly. |
| 546 | /// let mut data_grouped = Vec::new(); |
| 547 | /// for (key, group) in &data.into_iter().group_by(|elt| *elt >= 0) { |
| 548 | /// data_grouped.push((key, group.collect())); |
| 549 | /// } |
| 550 | /// assert_eq!(data_grouped, vec![(true, vec![1, 3]), (false, vec![-2, -2]), (true, vec![1, 0, 1, 2])]); |
| 551 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 552 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 553 | fn group_by<K, F>(self, key: F) -> GroupBy<K, Self, F> |
| 554 | where Self: Sized, |
| 555 | F: FnMut(&Self::Item) -> K, |
| 556 | K: PartialEq, |
| 557 | { |
| 558 | groupbylazy::new(self, key) |
| 559 | } |
| 560 | |
| 561 | /// Return an *iterable* that can chunk the iterator. |
| 562 | /// |
| 563 | /// Yield subiterators (chunks) that each yield a fixed number elements, |
| 564 | /// determined by `size`. The last chunk will be shorter if there aren't |
| 565 | /// enough elements. |
| 566 | /// |
| 567 | /// `IntoChunks` is based on `GroupBy`: it is iterable (implements |
| 568 | /// `IntoIterator`, **not** `Iterator`), and it only buffers if several |
| 569 | /// chunk iterators are alive at the same time. |
| 570 | /// |
| 571 | /// Iterator element type is `Chunk`, each chunk's iterator. |
| 572 | /// |
| 573 | /// **Panics** if `size` is 0. |
| 574 | /// |
| 575 | /// ``` |
| 576 | /// use itertools::Itertools; |
| 577 | /// |
| 578 | /// let data = vec![1, 1, 2, -2, 6, 0, 3, 1]; |
| 579 | /// //chunk size=3 |------->|-------->|--->| |
| 580 | /// |
| 581 | /// // Note: The `&` is significant here, `IntoChunks` is iterable |
| 582 | /// // only by reference. You can also call `.into_iter()` explicitly. |
| 583 | /// for chunk in &data.into_iter().chunks(3) { |
| 584 | /// // Check that the sum of each chunk is 4. |
| 585 | /// assert_eq!(4, chunk.sum()); |
| 586 | /// } |
| 587 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 588 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 589 | fn chunks(self, size: usize) -> IntoChunks<Self> |
| 590 | where Self: Sized, |
| 591 | { |
| 592 | assert!(size != 0); |
| 593 | groupbylazy::new_chunks(self, size) |
| 594 | } |
| 595 | |
| 596 | /// Return an iterator over all contiguous windows producing tuples of |
| 597 | /// a specific size (up to 4). |
| 598 | /// |
| 599 | /// `tuple_windows` clones the iterator elements so that they can be |
| 600 | /// part of successive windows, this makes it most suited for iterators |
| 601 | /// of references and other values that are cheap to copy. |
| 602 | /// |
| 603 | /// ``` |
| 604 | /// use itertools::Itertools; |
| 605 | /// let mut v = Vec::new(); |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 606 | /// |
| 607 | /// // pairwise iteration |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 608 | /// for (a, b) in (1..5).tuple_windows() { |
| 609 | /// v.push((a, b)); |
| 610 | /// } |
| 611 | /// assert_eq!(v, vec![(1, 2), (2, 3), (3, 4)]); |
| 612 | /// |
| 613 | /// let mut it = (1..5).tuple_windows(); |
| 614 | /// assert_eq!(Some((1, 2, 3)), it.next()); |
| 615 | /// assert_eq!(Some((2, 3, 4)), it.next()); |
| 616 | /// assert_eq!(None, it.next()); |
| 617 | /// |
| 618 | /// // this requires a type hint |
| 619 | /// let it = (1..5).tuple_windows::<(_, _, _)>(); |
| 620 | /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); |
| 621 | /// |
| 622 | /// // you can also specify the complete type |
| 623 | /// use itertools::TupleWindows; |
| 624 | /// use std::ops::Range; |
| 625 | /// |
| 626 | /// let it: TupleWindows<Range<u32>, (u32, u32, u32)> = (1..5).tuple_windows(); |
| 627 | /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); |
| 628 | /// ``` |
| 629 | fn tuple_windows<T>(self) -> TupleWindows<Self, T> |
| 630 | where Self: Sized + Iterator<Item = T::Item>, |
| 631 | T: traits::HomogeneousTuple, |
| 632 | T::Item: Clone |
| 633 | { |
| 634 | tuple_impl::tuple_windows(self) |
| 635 | } |
| 636 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 637 | /// Return an iterator over all windows, wrapping back to the first |
| 638 | /// elements when the window would otherwise exceed the length of the |
| 639 | /// iterator, producing tuples of a specific size (up to 4). |
| 640 | /// |
| 641 | /// `circular_tuple_windows` clones the iterator elements so that they can be |
| 642 | /// part of successive windows, this makes it most suited for iterators |
| 643 | /// of references and other values that are cheap to copy. |
| 644 | /// |
| 645 | /// ``` |
| 646 | /// use itertools::Itertools; |
| 647 | /// let mut v = Vec::new(); |
| 648 | /// for (a, b) in (1..5).circular_tuple_windows() { |
| 649 | /// v.push((a, b)); |
| 650 | /// } |
| 651 | /// assert_eq!(v, vec![(1, 2), (2, 3), (3, 4), (4, 1)]); |
| 652 | /// |
| 653 | /// let mut it = (1..5).circular_tuple_windows(); |
| 654 | /// assert_eq!(Some((1, 2, 3)), it.next()); |
| 655 | /// assert_eq!(Some((2, 3, 4)), it.next()); |
| 656 | /// assert_eq!(Some((3, 4, 1)), it.next()); |
| 657 | /// assert_eq!(Some((4, 1, 2)), it.next()); |
| 658 | /// assert_eq!(None, it.next()); |
| 659 | /// |
| 660 | /// // this requires a type hint |
| 661 | /// let it = (1..5).circular_tuple_windows::<(_, _, _)>(); |
| 662 | /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4), (3, 4, 1), (4, 1, 2)]); |
| 663 | /// ``` |
| 664 | fn circular_tuple_windows<T>(self) -> CircularTupleWindows<Self, T> |
| 665 | where Self: Sized + Clone + Iterator<Item = T::Item> + ExactSizeIterator, |
| 666 | T: tuple_impl::TupleCollect + Clone, |
| 667 | T::Item: Clone |
| 668 | { |
| 669 | tuple_impl::circular_tuple_windows(self) |
| 670 | } |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 671 | /// Return an iterator that groups the items in tuples of a specific size |
| 672 | /// (up to 4). |
| 673 | /// |
| 674 | /// See also the method [`.next_tuple()`](#method.next_tuple). |
| 675 | /// |
| 676 | /// ``` |
| 677 | /// use itertools::Itertools; |
| 678 | /// let mut v = Vec::new(); |
| 679 | /// for (a, b) in (1..5).tuples() { |
| 680 | /// v.push((a, b)); |
| 681 | /// } |
| 682 | /// assert_eq!(v, vec![(1, 2), (3, 4)]); |
| 683 | /// |
| 684 | /// let mut it = (1..7).tuples(); |
| 685 | /// assert_eq!(Some((1, 2, 3)), it.next()); |
| 686 | /// assert_eq!(Some((4, 5, 6)), it.next()); |
| 687 | /// assert_eq!(None, it.next()); |
| 688 | /// |
| 689 | /// // this requires a type hint |
| 690 | /// let it = (1..7).tuples::<(_, _, _)>(); |
| 691 | /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); |
| 692 | /// |
| 693 | /// // you can also specify the complete type |
| 694 | /// use itertools::Tuples; |
| 695 | /// use std::ops::Range; |
| 696 | /// |
| 697 | /// let it: Tuples<Range<u32>, (u32, u32, u32)> = (1..7).tuples(); |
| 698 | /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); |
| 699 | /// ``` |
| 700 | /// |
| 701 | /// See also [`Tuples::into_buffer`](structs/struct.Tuples.html#method.into_buffer). |
| 702 | fn tuples<T>(self) -> Tuples<Self, T> |
| 703 | where Self: Sized + Iterator<Item = T::Item>, |
| 704 | T: traits::HomogeneousTuple |
| 705 | { |
| 706 | tuple_impl::tuples(self) |
| 707 | } |
| 708 | |
| 709 | /// Split into an iterator pair that both yield all elements from |
| 710 | /// the original iterator. |
| 711 | /// |
| 712 | /// **Note:** If the iterator is clonable, prefer using that instead |
| 713 | /// of using this method. It is likely to be more efficient. |
| 714 | /// |
| 715 | /// Iterator element type is `Self::Item`. |
| 716 | /// |
| 717 | /// ``` |
| 718 | /// use itertools::Itertools; |
| 719 | /// let xs = vec![0, 1, 2, 3]; |
| 720 | /// |
| 721 | /// let (mut t1, t2) = xs.into_iter().tee(); |
| 722 | /// itertools::assert_equal(t1.next(), Some(0)); |
| 723 | /// itertools::assert_equal(t2, 0..4); |
| 724 | /// itertools::assert_equal(t1, 1..4); |
| 725 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 726 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 727 | fn tee(self) -> (Tee<Self>, Tee<Self>) |
| 728 | where Self: Sized, |
| 729 | Self::Item: Clone |
| 730 | { |
| 731 | tee::new(self) |
| 732 | } |
| 733 | |
| 734 | /// Return an iterator adaptor that steps `n` elements in the base iterator |
| 735 | /// for each iteration. |
| 736 | /// |
| 737 | /// The iterator steps by yielding the next element from the base iterator, |
| 738 | /// then skipping forward `n - 1` elements. |
| 739 | /// |
| 740 | /// Iterator element type is `Self::Item`. |
| 741 | /// |
| 742 | /// **Panics** if the step is 0. |
| 743 | /// |
| 744 | /// ``` |
| 745 | /// use itertools::Itertools; |
| 746 | /// |
| 747 | /// let it = (0..8).step(3); |
| 748 | /// itertools::assert_equal(it, vec![0, 3, 6]); |
| 749 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 750 | #[deprecated(note="Use std .step_by() instead", since="0.8.0")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 751 | #[allow(deprecated)] |
| 752 | fn step(self, n: usize) -> Step<Self> |
| 753 | where Self: Sized |
| 754 | { |
| 755 | adaptors::step(self, n) |
| 756 | } |
| 757 | |
| 758 | /// Convert each item of the iterator using the `Into` trait. |
| 759 | /// |
| 760 | /// ```rust |
| 761 | /// use itertools::Itertools; |
| 762 | /// |
| 763 | /// (1i32..42i32).map_into::<f64>().collect_vec(); |
| 764 | /// ``` |
| 765 | fn map_into<R>(self) -> MapInto<Self, R> |
| 766 | where Self: Sized, |
| 767 | Self::Item: Into<R>, |
| 768 | { |
| 769 | adaptors::map_into(self) |
| 770 | } |
| 771 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 772 | /// See [`.map_ok()`](#method.map_ok). |
| 773 | #[deprecated(note="Use .map_ok() instead", since="0.10.0")] |
| 774 | fn map_results<F, T, U, E>(self, f: F) -> MapOk<Self, F> |
| 775 | where Self: Iterator<Item = Result<T, E>> + Sized, |
| 776 | F: FnMut(T) -> U, |
| 777 | { |
| 778 | self.map_ok(f) |
| 779 | } |
| 780 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 781 | /// Return an iterator adaptor that applies the provided closure |
| 782 | /// to every `Result::Ok` value. `Result::Err` values are |
| 783 | /// unchanged. |
| 784 | /// |
| 785 | /// ``` |
| 786 | /// use itertools::Itertools; |
| 787 | /// |
| 788 | /// let input = vec![Ok(41), Err(false), Ok(11)]; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 789 | /// let it = input.into_iter().map_ok(|i| i + 1); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 790 | /// itertools::assert_equal(it, vec![Ok(42), Err(false), Ok(12)]); |
| 791 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 792 | fn map_ok<F, T, U, E>(self, f: F) -> MapOk<Self, F> |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 793 | where Self: Iterator<Item = Result<T, E>> + Sized, |
| 794 | F: FnMut(T) -> U, |
| 795 | { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 796 | adaptors::map_ok(self, f) |
| 797 | } |
| 798 | |
| 799 | /// Return an iterator adaptor that filters every `Result::Ok` |
| 800 | /// value with the provided closure. `Result::Err` values are |
| 801 | /// unchanged. |
| 802 | /// |
| 803 | /// ``` |
| 804 | /// use itertools::Itertools; |
| 805 | /// |
| 806 | /// let input = vec![Ok(22), Err(false), Ok(11)]; |
| 807 | /// let it = input.into_iter().filter_ok(|&i| i > 20); |
| 808 | /// itertools::assert_equal(it, vec![Ok(22), Err(false)]); |
| 809 | /// ``` |
| 810 | fn filter_ok<F, T, E>(self, f: F) -> FilterOk<Self, F> |
| 811 | where Self: Iterator<Item = Result<T, E>> + Sized, |
| 812 | F: FnMut(&T) -> bool, |
| 813 | { |
| 814 | adaptors::filter_ok(self, f) |
| 815 | } |
| 816 | |
| 817 | /// Return an iterator adaptor that filters and transforms every |
| 818 | /// `Result::Ok` value with the provided closure. `Result::Err` |
| 819 | /// values are unchanged. |
| 820 | /// |
| 821 | /// ``` |
| 822 | /// use itertools::Itertools; |
| 823 | /// |
| 824 | /// let input = vec![Ok(22), Err(false), Ok(11)]; |
| 825 | /// let it = input.into_iter().filter_map_ok(|i| if i > 20 { Some(i * 2) } else { None }); |
| 826 | /// itertools::assert_equal(it, vec![Ok(44), Err(false)]); |
| 827 | /// ``` |
| 828 | fn filter_map_ok<F, T, U, E>(self, f: F) -> FilterMapOk<Self, F> |
| 829 | where Self: Iterator<Item = Result<T, E>> + Sized, |
| 830 | F: FnMut(T) -> Option<U>, |
| 831 | { |
| 832 | adaptors::filter_map_ok(self, f) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 833 | } |
| 834 | |
| 835 | /// Return an iterator adaptor that merges the two base iterators in |
| 836 | /// ascending order. If both base iterators are sorted (ascending), the |
| 837 | /// result is sorted. |
| 838 | /// |
| 839 | /// Iterator element type is `Self::Item`. |
| 840 | /// |
| 841 | /// ``` |
| 842 | /// use itertools::Itertools; |
| 843 | /// |
| 844 | /// let a = (0..11).step(3); |
| 845 | /// let b = (0..11).step(5); |
| 846 | /// let it = a.merge(b); |
| 847 | /// itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]); |
| 848 | /// ``` |
| 849 | fn merge<J>(self, other: J) -> Merge<Self, J::IntoIter> |
| 850 | where Self: Sized, |
| 851 | Self::Item: PartialOrd, |
| 852 | J: IntoIterator<Item = Self::Item> |
| 853 | { |
| 854 | merge(self, other) |
| 855 | } |
| 856 | |
| 857 | /// Return an iterator adaptor that merges the two base iterators in order. |
| 858 | /// This is much like `.merge()` but allows for a custom ordering. |
| 859 | /// |
| 860 | /// This can be especially useful for sequences of tuples. |
| 861 | /// |
| 862 | /// Iterator element type is `Self::Item`. |
| 863 | /// |
| 864 | /// ``` |
| 865 | /// use itertools::Itertools; |
| 866 | /// |
| 867 | /// let a = (0..).zip("bc".chars()); |
| 868 | /// let b = (0..).zip("ad".chars()); |
| 869 | /// let it = a.merge_by(b, |x, y| x.1 <= y.1); |
| 870 | /// itertools::assert_equal(it, vec![(0, 'a'), (0, 'b'), (1, 'c'), (1, 'd')]); |
| 871 | /// ``` |
| 872 | |
| 873 | fn merge_by<J, F>(self, other: J, is_first: F) -> MergeBy<Self, J::IntoIter, F> |
| 874 | where Self: Sized, |
| 875 | J: IntoIterator<Item = Self::Item>, |
| 876 | F: FnMut(&Self::Item, &Self::Item) -> bool |
| 877 | { |
| 878 | adaptors::merge_by_new(self, other.into_iter(), is_first) |
| 879 | } |
| 880 | |
| 881 | /// Create an iterator that merges items from both this and the specified |
| 882 | /// iterator in ascending order. |
| 883 | /// |
| 884 | /// It chooses whether to pair elements based on the `Ordering` returned by the |
| 885 | /// specified compare function. At any point, inspecting the tip of the |
| 886 | /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type |
| 887 | /// `J::Item` respectively, the resulting iterator will: |
| 888 | /// |
| 889 | /// - Emit `EitherOrBoth::Left(i)` when `i < j`, |
| 890 | /// and remove `i` from its source iterator |
| 891 | /// - Emit `EitherOrBoth::Right(j)` when `i > j`, |
| 892 | /// and remove `j` from its source iterator |
| 893 | /// - Emit `EitherOrBoth::Both(i, j)` when `i == j`, |
| 894 | /// and remove both `i` and `j` from their respective source iterators |
| 895 | /// |
| 896 | /// ``` |
| 897 | /// use itertools::Itertools; |
| 898 | /// use itertools::EitherOrBoth::{Left, Right, Both}; |
| 899 | /// |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 900 | /// let multiples_of_2 = (0..10).step(2); |
| 901 | /// let multiples_of_3 = (0..10).step(3); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 902 | /// |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 903 | /// itertools::assert_equal( |
| 904 | /// multiples_of_2.merge_join_by(multiples_of_3, |i, j| i.cmp(j)), |
| 905 | /// vec![Both(0, 0), Left(2), Right(3), Left(4), Both(6, 6), Left(8), Right(9)] |
| 906 | /// ); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 907 | /// ``` |
| 908 | #[inline] |
| 909 | fn merge_join_by<J, F>(self, other: J, cmp_fn: F) -> MergeJoinBy<Self, J::IntoIter, F> |
| 910 | where J: IntoIterator, |
| 911 | F: FnMut(&Self::Item, &J::Item) -> std::cmp::Ordering, |
| 912 | Self: Sized |
| 913 | { |
| 914 | merge_join_by(self, other, cmp_fn) |
| 915 | } |
| 916 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 917 | /// Return an iterator adaptor that flattens an iterator of iterators by |
| 918 | /// merging them in ascending order. |
| 919 | /// |
| 920 | /// If all base iterators are sorted (ascending), the result is sorted. |
| 921 | /// |
| 922 | /// Iterator element type is `Self::Item`. |
| 923 | /// |
| 924 | /// ``` |
| 925 | /// use itertools::Itertools; |
| 926 | /// |
| 927 | /// let a = (0..6).step(3); |
| 928 | /// let b = (1..6).step(3); |
| 929 | /// let c = (2..6).step(3); |
| 930 | /// let it = vec![a, b, c].into_iter().kmerge(); |
| 931 | /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]); |
| 932 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 933 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 934 | fn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter> |
| 935 | where Self: Sized, |
| 936 | Self::Item: IntoIterator, |
| 937 | <Self::Item as IntoIterator>::Item: PartialOrd, |
| 938 | { |
| 939 | kmerge(self) |
| 940 | } |
| 941 | |
| 942 | /// Return an iterator adaptor that flattens an iterator of iterators by |
| 943 | /// merging them according to the given closure. |
| 944 | /// |
| 945 | /// The closure `first` is called with two elements *a*, *b* and should |
| 946 | /// return `true` if *a* is ordered before *b*. |
| 947 | /// |
| 948 | /// If all base iterators are sorted according to `first`, the result is |
| 949 | /// sorted. |
| 950 | /// |
| 951 | /// Iterator element type is `Self::Item`. |
| 952 | /// |
| 953 | /// ``` |
| 954 | /// use itertools::Itertools; |
| 955 | /// |
| 956 | /// let a = vec![-1f64, 2., 3., -5., 6., -7.]; |
| 957 | /// let b = vec![0., 2., -4.]; |
| 958 | /// let mut it = vec![a, b].into_iter().kmerge_by(|a, b| a.abs() < b.abs()); |
| 959 | /// assert_eq!(it.next(), Some(0.)); |
| 960 | /// assert_eq!(it.last(), Some(-7.)); |
| 961 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 962 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 963 | fn kmerge_by<F>(self, first: F) |
| 964 | -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F> |
| 965 | where Self: Sized, |
| 966 | Self::Item: IntoIterator, |
| 967 | F: FnMut(&<Self::Item as IntoIterator>::Item, |
| 968 | &<Self::Item as IntoIterator>::Item) -> bool |
| 969 | { |
| 970 | kmerge_by(self, first) |
| 971 | } |
| 972 | |
| 973 | /// Return an iterator adaptor that iterates over the cartesian product of |
| 974 | /// the element sets of two iterators `self` and `J`. |
| 975 | /// |
| 976 | /// Iterator element type is `(Self::Item, J::Item)`. |
| 977 | /// |
| 978 | /// ``` |
| 979 | /// use itertools::Itertools; |
| 980 | /// |
| 981 | /// let it = (0..2).cartesian_product("αβ".chars()); |
| 982 | /// itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]); |
| 983 | /// ``` |
| 984 | fn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoIter> |
| 985 | where Self: Sized, |
| 986 | Self::Item: Clone, |
| 987 | J: IntoIterator, |
| 988 | J::IntoIter: Clone |
| 989 | { |
| 990 | adaptors::cartesian_product(self, other.into_iter()) |
| 991 | } |
| 992 | |
| 993 | /// Return an iterator adaptor that iterates over the cartesian product of |
| 994 | /// all subiterators returned by meta-iterator `self`. |
| 995 | /// |
| 996 | /// All provided iterators must yield the same `Item` type. To generate |
| 997 | /// the product of iterators yielding multiple types, use the |
| 998 | /// [`iproduct`](macro.iproduct.html) macro instead. |
| 999 | /// |
| 1000 | /// |
| 1001 | /// The iterator element type is `Vec<T>`, where `T` is the iterator element |
| 1002 | /// of the subiterators. |
| 1003 | /// |
| 1004 | /// ``` |
| 1005 | /// use itertools::Itertools; |
| 1006 | /// let mut multi_prod = (0..3).map(|i| (i * 2)..(i * 2 + 2)) |
| 1007 | /// .multi_cartesian_product(); |
| 1008 | /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 4])); |
| 1009 | /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 5])); |
| 1010 | /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 4])); |
| 1011 | /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 5])); |
| 1012 | /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 4])); |
| 1013 | /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 5])); |
| 1014 | /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 4])); |
| 1015 | /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 5])); |
| 1016 | /// assert_eq!(multi_prod.next(), None); |
| 1017 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1018 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1019 | fn multi_cartesian_product(self) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter> |
| 1020 | where Self: Iterator + Sized, |
| 1021 | Self::Item: IntoIterator, |
| 1022 | <Self::Item as IntoIterator>::IntoIter: Clone, |
| 1023 | <Self::Item as IntoIterator>::Item: Clone |
| 1024 | { |
| 1025 | adaptors::multi_cartesian_product(self) |
| 1026 | } |
| 1027 | |
| 1028 | /// Return an iterator adaptor that uses the passed-in closure to |
| 1029 | /// optionally merge together consecutive elements. |
| 1030 | /// |
| 1031 | /// The closure `f` is passed two elements, `previous` and `current` and may |
| 1032 | /// return either (1) `Ok(combined)` to merge the two values or |
| 1033 | /// (2) `Err((previous', current'))` to indicate they can't be merged. |
| 1034 | /// In (2), the value `previous'` is emitted by the iterator. |
| 1035 | /// Either (1) `combined` or (2) `current'` becomes the previous value |
| 1036 | /// when coalesce continues with the next pair of elements to merge. The |
| 1037 | /// value that remains at the end is also emitted by the iterator. |
| 1038 | /// |
| 1039 | /// Iterator element type is `Self::Item`. |
| 1040 | /// |
| 1041 | /// This iterator is *fused*. |
| 1042 | /// |
| 1043 | /// ``` |
| 1044 | /// use itertools::Itertools; |
| 1045 | /// |
| 1046 | /// // sum same-sign runs together |
| 1047 | /// let data = vec![-1., -2., -3., 3., 1., 0., -1.]; |
| 1048 | /// itertools::assert_equal(data.into_iter().coalesce(|x, y| |
| 1049 | /// if (x >= 0.) == (y >= 0.) { |
| 1050 | /// Ok(x + y) |
| 1051 | /// } else { |
| 1052 | /// Err((x, y)) |
| 1053 | /// }), |
| 1054 | /// vec![-6., 4., -1.]); |
| 1055 | /// ``` |
| 1056 | fn coalesce<F>(self, f: F) -> Coalesce<Self, F> |
| 1057 | where Self: Sized, |
| 1058 | F: FnMut(Self::Item, Self::Item) |
| 1059 | -> Result<Self::Item, (Self::Item, Self::Item)> |
| 1060 | { |
| 1061 | adaptors::coalesce(self, f) |
| 1062 | } |
| 1063 | |
| 1064 | /// Remove duplicates from sections of consecutive identical elements. |
| 1065 | /// If the iterator is sorted, all elements will be unique. |
| 1066 | /// |
| 1067 | /// Iterator element type is `Self::Item`. |
| 1068 | /// |
| 1069 | /// This iterator is *fused*. |
| 1070 | /// |
| 1071 | /// ``` |
| 1072 | /// use itertools::Itertools; |
| 1073 | /// |
| 1074 | /// let data = vec![1., 1., 2., 3., 3., 2., 2.]; |
| 1075 | /// itertools::assert_equal(data.into_iter().dedup(), |
| 1076 | /// vec![1., 2., 3., 2.]); |
| 1077 | /// ``` |
| 1078 | fn dedup(self) -> Dedup<Self> |
| 1079 | where Self: Sized, |
| 1080 | Self::Item: PartialEq, |
| 1081 | { |
| 1082 | adaptors::dedup(self) |
| 1083 | } |
| 1084 | |
| 1085 | /// Remove duplicates from sections of consecutive identical elements, |
| 1086 | /// determining equality using a comparison function. |
| 1087 | /// If the iterator is sorted, all elements will be unique. |
| 1088 | /// |
| 1089 | /// Iterator element type is `Self::Item`. |
| 1090 | /// |
| 1091 | /// This iterator is *fused*. |
| 1092 | /// |
| 1093 | /// ``` |
| 1094 | /// use itertools::Itertools; |
| 1095 | /// |
| 1096 | /// let data = vec![(0, 1.), (1, 1.), (0, 2.), (0, 3.), (1, 3.), (1, 2.), (2, 2.)]; |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1097 | /// itertools::assert_equal(data.into_iter().dedup_by(|x, y| x.1 == y.1), |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1098 | /// vec![(0, 1.), (0, 2.), (0, 3.), (1, 2.)]); |
| 1099 | /// ``` |
| 1100 | fn dedup_by<Cmp>(self, cmp: Cmp) -> DedupBy<Self, Cmp> |
| 1101 | where Self: Sized, |
| 1102 | Cmp: FnMut(&Self::Item, &Self::Item)->bool, |
| 1103 | { |
| 1104 | adaptors::dedup_by(self, cmp) |
| 1105 | } |
| 1106 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1107 | /// Remove duplicates from sections of consecutive identical elements, while keeping a count of |
| 1108 | /// how many repeated elements were present. |
| 1109 | /// If the iterator is sorted, all elements will be unique. |
| 1110 | /// |
| 1111 | /// Iterator element type is `(usize, Self::Item)`. |
| 1112 | /// |
| 1113 | /// This iterator is *fused*. |
| 1114 | /// |
| 1115 | /// ``` |
| 1116 | /// use itertools::Itertools; |
| 1117 | /// |
| 1118 | /// let data = vec![1., 1., 2., 3., 3., 2., 2.]; |
| 1119 | /// itertools::assert_equal(data.into_iter().dedup_with_count(), |
| 1120 | /// vec![(2, 1.), (1, 2.), (2, 3.), (2, 2.)]); |
| 1121 | /// ``` |
| 1122 | fn dedup_with_count(self) -> DedupWithCount<Self> |
| 1123 | where Self: Sized, |
| 1124 | { |
| 1125 | adaptors::dedup_with_count(self) |
| 1126 | } |
| 1127 | |
| 1128 | /// Remove duplicates from sections of consecutive identical elements, while keeping a count of |
| 1129 | /// how many repeated elements were present. |
| 1130 | /// This will determine equality using a comparison function. |
| 1131 | /// If the iterator is sorted, all elements will be unique. |
| 1132 | /// |
| 1133 | /// Iterator element type is `(usize, Self::Item)`. |
| 1134 | /// |
| 1135 | /// This iterator is *fused*. |
| 1136 | /// |
| 1137 | /// ``` |
| 1138 | /// use itertools::Itertools; |
| 1139 | /// |
| 1140 | /// let data = vec![(0, 1.), (1, 1.), (0, 2.), (0, 3.), (1, 3.), (1, 2.), (2, 2.)]; |
| 1141 | /// itertools::assert_equal(data.into_iter().dedup_by_with_count(|x, y| x.1 == y.1), |
| 1142 | /// vec![(2, (0, 1.)), (1, (0, 2.)), (2, (0, 3.)), (2, (1, 2.))]); |
| 1143 | /// ``` |
| 1144 | fn dedup_by_with_count<Cmp>(self, cmp: Cmp) -> DedupByWithCount<Self, Cmp> |
| 1145 | where Self: Sized, |
| 1146 | Cmp: FnMut(&Self::Item, &Self::Item) -> bool, |
| 1147 | { |
| 1148 | adaptors::dedup_by_with_count(self, cmp) |
| 1149 | } |
| 1150 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1151 | /// Return an iterator adaptor that filters out elements that have |
| 1152 | /// already been produced once during the iteration. Duplicates |
| 1153 | /// are detected using hash and equality. |
| 1154 | /// |
| 1155 | /// Clones of visited elements are stored in a hash set in the |
| 1156 | /// iterator. |
| 1157 | /// |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1158 | /// The iterator is stable, returning the non-duplicate items in the order |
| 1159 | /// in which they occur in the adapted iterator. In a set of duplicate |
| 1160 | /// items, the first item encountered is the item retained. |
| 1161 | /// |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1162 | /// ``` |
| 1163 | /// use itertools::Itertools; |
| 1164 | /// |
| 1165 | /// let data = vec![10, 20, 30, 20, 40, 10, 50]; |
| 1166 | /// itertools::assert_equal(data.into_iter().unique(), |
| 1167 | /// vec![10, 20, 30, 40, 50]); |
| 1168 | /// ``` |
| 1169 | #[cfg(feature = "use_std")] |
| 1170 | fn unique(self) -> Unique<Self> |
| 1171 | where Self: Sized, |
| 1172 | Self::Item: Clone + Eq + Hash |
| 1173 | { |
| 1174 | unique_impl::unique(self) |
| 1175 | } |
| 1176 | |
| 1177 | /// Return an iterator adaptor that filters out elements that have |
| 1178 | /// already been produced once during the iteration. |
| 1179 | /// |
| 1180 | /// Duplicates are detected by comparing the key they map to |
| 1181 | /// with the keying function `f` by hash and equality. |
| 1182 | /// The keys are stored in a hash set in the iterator. |
| 1183 | /// |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1184 | /// The iterator is stable, returning the non-duplicate items in the order |
| 1185 | /// in which they occur in the adapted iterator. In a set of duplicate |
| 1186 | /// items, the first item encountered is the item retained. |
| 1187 | /// |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1188 | /// ``` |
| 1189 | /// use itertools::Itertools; |
| 1190 | /// |
| 1191 | /// let data = vec!["a", "bb", "aa", "c", "ccc"]; |
| 1192 | /// itertools::assert_equal(data.into_iter().unique_by(|s| s.len()), |
| 1193 | /// vec!["a", "bb", "ccc"]); |
| 1194 | /// ``` |
| 1195 | #[cfg(feature = "use_std")] |
| 1196 | fn unique_by<V, F>(self, f: F) -> UniqueBy<Self, V, F> |
| 1197 | where Self: Sized, |
| 1198 | V: Eq + Hash, |
| 1199 | F: FnMut(&Self::Item) -> V |
| 1200 | { |
| 1201 | unique_impl::unique_by(self, f) |
| 1202 | } |
| 1203 | |
| 1204 | /// Return an iterator adaptor that borrows from this iterator and |
| 1205 | /// takes items while the closure `accept` returns `true`. |
| 1206 | /// |
| 1207 | /// This adaptor can only be used on iterators that implement `PeekingNext` |
| 1208 | /// like `.peekable()`, `put_back` and a few other collection iterators. |
| 1209 | /// |
| 1210 | /// The last and rejected element (first `false`) is still available when |
| 1211 | /// `peeking_take_while` is done. |
| 1212 | /// |
| 1213 | /// |
| 1214 | /// See also [`.take_while_ref()`](#method.take_while_ref) |
| 1215 | /// which is a similar adaptor. |
| 1216 | fn peeking_take_while<F>(&mut self, accept: F) -> PeekingTakeWhile<Self, F> |
| 1217 | where Self: Sized + PeekingNext, |
| 1218 | F: FnMut(&Self::Item) -> bool, |
| 1219 | { |
| 1220 | peeking_take_while::peeking_take_while(self, accept) |
| 1221 | } |
| 1222 | |
| 1223 | /// Return an iterator adaptor that borrows from a `Clone`-able iterator |
| 1224 | /// to only pick off elements while the predicate `accept` returns `true`. |
| 1225 | /// |
| 1226 | /// It uses the `Clone` trait to restore the original iterator so that the |
| 1227 | /// last and rejected element (first `false`) is still available when |
| 1228 | /// `take_while_ref` is done. |
| 1229 | /// |
| 1230 | /// ``` |
| 1231 | /// use itertools::Itertools; |
| 1232 | /// |
| 1233 | /// let mut hexadecimals = "0123456789abcdef".chars(); |
| 1234 | /// |
| 1235 | /// let decimals = hexadecimals.take_while_ref(|c| c.is_numeric()) |
| 1236 | /// .collect::<String>(); |
| 1237 | /// assert_eq!(decimals, "0123456789"); |
| 1238 | /// assert_eq!(hexadecimals.next(), Some('a')); |
| 1239 | /// |
| 1240 | /// ``` |
| 1241 | fn take_while_ref<F>(&mut self, accept: F) -> TakeWhileRef<Self, F> |
| 1242 | where Self: Clone, |
| 1243 | F: FnMut(&Self::Item) -> bool |
| 1244 | { |
| 1245 | adaptors::take_while_ref(self, accept) |
| 1246 | } |
| 1247 | |
| 1248 | /// Return an iterator adaptor that filters `Option<A>` iterator elements |
| 1249 | /// and produces `A`. Stops on the first `None` encountered. |
| 1250 | /// |
| 1251 | /// Iterator element type is `A`, the unwrapped element. |
| 1252 | /// |
| 1253 | /// ``` |
| 1254 | /// use itertools::Itertools; |
| 1255 | /// |
| 1256 | /// // List all hexadecimal digits |
| 1257 | /// itertools::assert_equal( |
| 1258 | /// (0..).map(|i| std::char::from_digit(i, 16)).while_some(), |
| 1259 | /// "0123456789abcdef".chars()); |
| 1260 | /// |
| 1261 | /// ``` |
| 1262 | fn while_some<A>(self) -> WhileSome<Self> |
| 1263 | where Self: Sized + Iterator<Item = Option<A>> |
| 1264 | { |
| 1265 | adaptors::while_some(self) |
| 1266 | } |
| 1267 | |
| 1268 | /// Return an iterator adaptor that iterates over the combinations of the |
| 1269 | /// elements from an iterator. |
| 1270 | /// |
| 1271 | /// Iterator element can be any homogeneous tuple of type `Self::Item` with |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1272 | /// size up to 12. |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1273 | /// |
| 1274 | /// ``` |
| 1275 | /// use itertools::Itertools; |
| 1276 | /// |
| 1277 | /// let mut v = Vec::new(); |
| 1278 | /// for (a, b) in (1..5).tuple_combinations() { |
| 1279 | /// v.push((a, b)); |
| 1280 | /// } |
| 1281 | /// assert_eq!(v, vec![(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]); |
| 1282 | /// |
| 1283 | /// let mut it = (1..5).tuple_combinations(); |
| 1284 | /// assert_eq!(Some((1, 2, 3)), it.next()); |
| 1285 | /// assert_eq!(Some((1, 2, 4)), it.next()); |
| 1286 | /// assert_eq!(Some((1, 3, 4)), it.next()); |
| 1287 | /// assert_eq!(Some((2, 3, 4)), it.next()); |
| 1288 | /// assert_eq!(None, it.next()); |
| 1289 | /// |
| 1290 | /// // this requires a type hint |
| 1291 | /// let it = (1..5).tuple_combinations::<(_, _, _)>(); |
| 1292 | /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); |
| 1293 | /// |
| 1294 | /// // you can also specify the complete type |
| 1295 | /// use itertools::TupleCombinations; |
| 1296 | /// use std::ops::Range; |
| 1297 | /// |
| 1298 | /// let it: TupleCombinations<Range<u32>, (u32, u32, u32)> = (1..5).tuple_combinations(); |
| 1299 | /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); |
| 1300 | /// ``` |
| 1301 | fn tuple_combinations<T>(self) -> TupleCombinations<Self, T> |
| 1302 | where Self: Sized + Clone, |
| 1303 | Self::Item: Clone, |
| 1304 | T: adaptors::HasCombination<Self>, |
| 1305 | { |
| 1306 | adaptors::tuple_combinations(self) |
| 1307 | } |
| 1308 | |
| 1309 | /// Return an iterator adaptor that iterates over the `k`-length combinations of |
| 1310 | /// the elements from an iterator. |
| 1311 | /// |
| 1312 | /// Iterator element type is `Vec<Self::Item>`. The iterator produces a new Vec per iteration, |
| 1313 | /// and clones the iterator elements. |
| 1314 | /// |
| 1315 | /// ``` |
| 1316 | /// use itertools::Itertools; |
| 1317 | /// |
| 1318 | /// let it = (1..5).combinations(3); |
| 1319 | /// itertools::assert_equal(it, vec![ |
| 1320 | /// vec![1, 2, 3], |
| 1321 | /// vec![1, 2, 4], |
| 1322 | /// vec![1, 3, 4], |
| 1323 | /// vec![2, 3, 4], |
| 1324 | /// ]); |
| 1325 | /// ``` |
| 1326 | /// |
| 1327 | /// Note: Combinations does not take into account the equality of the iterated values. |
| 1328 | /// ``` |
| 1329 | /// use itertools::Itertools; |
| 1330 | /// |
| 1331 | /// let it = vec![1, 2, 2].into_iter().combinations(2); |
| 1332 | /// itertools::assert_equal(it, vec![ |
| 1333 | /// vec![1, 2], // Note: these are the same |
| 1334 | /// vec![1, 2], // Note: these are the same |
| 1335 | /// vec![2, 2], |
| 1336 | /// ]); |
| 1337 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1338 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1339 | fn combinations(self, k: usize) -> Combinations<Self> |
| 1340 | where Self: Sized, |
| 1341 | Self::Item: Clone |
| 1342 | { |
| 1343 | combinations::combinations(self, k) |
| 1344 | } |
| 1345 | |
| 1346 | /// Return an iterator that iterates over the `k`-length combinations of |
| 1347 | /// the elements from an iterator, with replacement. |
| 1348 | /// |
| 1349 | /// Iterator element type is `Vec<Self::Item>`. The iterator produces a new Vec per iteration, |
| 1350 | /// and clones the iterator elements. |
| 1351 | /// |
| 1352 | /// ``` |
| 1353 | /// use itertools::Itertools; |
| 1354 | /// |
| 1355 | /// let it = (1..4).combinations_with_replacement(2); |
| 1356 | /// itertools::assert_equal(it, vec![ |
| 1357 | /// vec![1, 1], |
| 1358 | /// vec![1, 2], |
| 1359 | /// vec![1, 3], |
| 1360 | /// vec![2, 2], |
| 1361 | /// vec![2, 3], |
| 1362 | /// vec![3, 3], |
| 1363 | /// ]); |
| 1364 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1365 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1366 | fn combinations_with_replacement(self, k: usize) -> CombinationsWithReplacement<Self> |
| 1367 | where |
| 1368 | Self: Sized, |
| 1369 | Self::Item: Clone, |
| 1370 | { |
| 1371 | combinations_with_replacement::combinations_with_replacement(self, k) |
| 1372 | } |
| 1373 | |
| 1374 | /// Return an iterator adaptor that iterates over all k-permutations of the |
| 1375 | /// elements from an iterator. |
| 1376 | /// |
| 1377 | /// Iterator element type is `Vec<Self::Item>` with length `k`. The iterator |
| 1378 | /// produces a new Vec per iteration, and clones the iterator elements. |
| 1379 | /// |
| 1380 | /// If `k` is greater than the length of the input iterator, the resultant |
| 1381 | /// iterator adaptor will be empty. |
| 1382 | /// |
| 1383 | /// ``` |
| 1384 | /// use itertools::Itertools; |
| 1385 | /// |
| 1386 | /// let perms = (5..8).permutations(2); |
| 1387 | /// itertools::assert_equal(perms, vec![ |
| 1388 | /// vec![5, 6], |
| 1389 | /// vec![5, 7], |
| 1390 | /// vec![6, 5], |
| 1391 | /// vec![6, 7], |
| 1392 | /// vec![7, 5], |
| 1393 | /// vec![7, 6], |
| 1394 | /// ]); |
| 1395 | /// ``` |
| 1396 | /// |
| 1397 | /// Note: Permutations does not take into account the equality of the iterated values. |
| 1398 | /// |
| 1399 | /// ``` |
| 1400 | /// use itertools::Itertools; |
| 1401 | /// |
| 1402 | /// let it = vec![2, 2].into_iter().permutations(2); |
| 1403 | /// itertools::assert_equal(it, vec![ |
| 1404 | /// vec![2, 2], // Note: these are the same |
| 1405 | /// vec![2, 2], // Note: these are the same |
| 1406 | /// ]); |
| 1407 | /// ``` |
| 1408 | /// |
| 1409 | /// Note: The source iterator is collected lazily, and will not be |
| 1410 | /// re-iterated if the permutations adaptor is completed and re-iterated. |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1411 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1412 | fn permutations(self, k: usize) -> Permutations<Self> |
| 1413 | where Self: Sized, |
| 1414 | Self::Item: Clone |
| 1415 | { |
| 1416 | permutations::permutations(self, k) |
| 1417 | } |
| 1418 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1419 | /// Return an iterator that iterates through the powerset of the elements from an |
| 1420 | /// iterator. |
| 1421 | /// |
| 1422 | /// Iterator element type is `Vec<Self::Item>`. The iterator produces a new `Vec` |
| 1423 | /// per iteration, and clones the iterator elements. |
| 1424 | /// |
| 1425 | /// The powerset of a set contains all subsets including the empty set and the full |
| 1426 | /// input set. A powerset has length _2^n_ where _n_ is the length of the input |
| 1427 | /// set. |
| 1428 | /// |
| 1429 | /// Each `Vec` produced by this iterator represents a subset of the elements |
| 1430 | /// produced by the source iterator. |
| 1431 | /// |
| 1432 | /// ``` |
| 1433 | /// use itertools::Itertools; |
| 1434 | /// |
| 1435 | /// let sets = (1..4).powerset().collect::<Vec<_>>(); |
| 1436 | /// itertools::assert_equal(sets, vec![ |
| 1437 | /// vec![], |
| 1438 | /// vec![1], |
| 1439 | /// vec![2], |
| 1440 | /// vec![3], |
| 1441 | /// vec![1, 2], |
| 1442 | /// vec![1, 3], |
| 1443 | /// vec![2, 3], |
| 1444 | /// vec![1, 2, 3], |
| 1445 | /// ]); |
| 1446 | /// ``` |
| 1447 | #[cfg(feature = "use_alloc")] |
| 1448 | fn powerset(self) -> Powerset<Self> |
| 1449 | where Self: Sized, |
| 1450 | Self::Item: Clone, |
| 1451 | { |
| 1452 | powerset::powerset(self) |
| 1453 | } |
| 1454 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1455 | /// Return an iterator adaptor that pads the sequence to a minimum length of |
| 1456 | /// `min` by filling missing elements using a closure `f`. |
| 1457 | /// |
| 1458 | /// Iterator element type is `Self::Item`. |
| 1459 | /// |
| 1460 | /// ``` |
| 1461 | /// use itertools::Itertools; |
| 1462 | /// |
| 1463 | /// let it = (0..5).pad_using(10, |i| 2*i); |
| 1464 | /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 10, 12, 14, 16, 18]); |
| 1465 | /// |
| 1466 | /// let it = (0..10).pad_using(5, |i| 2*i); |
| 1467 | /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); |
| 1468 | /// |
| 1469 | /// let it = (0..5).pad_using(10, |i| 2*i).rev(); |
| 1470 | /// itertools::assert_equal(it, vec![18, 16, 14, 12, 10, 4, 3, 2, 1, 0]); |
| 1471 | /// ``` |
| 1472 | fn pad_using<F>(self, min: usize, f: F) -> PadUsing<Self, F> |
| 1473 | where Self: Sized, |
| 1474 | F: FnMut(usize) -> Self::Item |
| 1475 | { |
| 1476 | pad_tail::pad_using(self, min, f) |
| 1477 | } |
| 1478 | |
| 1479 | /// Return an iterator adaptor that wraps each element in a `Position` to |
| 1480 | /// ease special-case handling of the first or last elements. |
| 1481 | /// |
| 1482 | /// Iterator element type is |
| 1483 | /// [`Position<Self::Item>`](enum.Position.html) |
| 1484 | /// |
| 1485 | /// ``` |
| 1486 | /// use itertools::{Itertools, Position}; |
| 1487 | /// |
| 1488 | /// let it = (0..4).with_position(); |
| 1489 | /// itertools::assert_equal(it, |
| 1490 | /// vec![Position::First(0), |
| 1491 | /// Position::Middle(1), |
| 1492 | /// Position::Middle(2), |
| 1493 | /// Position::Last(3)]); |
| 1494 | /// |
| 1495 | /// let it = (0..1).with_position(); |
| 1496 | /// itertools::assert_equal(it, vec![Position::Only(0)]); |
| 1497 | /// ``` |
| 1498 | fn with_position(self) -> WithPosition<Self> |
| 1499 | where Self: Sized, |
| 1500 | { |
| 1501 | with_position::with_position(self) |
| 1502 | } |
| 1503 | |
| 1504 | /// Return an iterator adaptor that yields the indices of all elements |
| 1505 | /// satisfying a predicate, counted from the start of the iterator. |
| 1506 | /// |
| 1507 | /// Equivalent to `iter.enumerate().filter(|(_, v)| predicate(v)).map(|(i, _)| i)`. |
| 1508 | /// |
| 1509 | /// ``` |
| 1510 | /// use itertools::Itertools; |
| 1511 | /// |
| 1512 | /// let data = vec![1, 2, 3, 3, 4, 6, 7, 9]; |
| 1513 | /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 0), vec![1, 4, 5]); |
| 1514 | /// |
| 1515 | /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 1).rev(), vec![7, 6, 3, 2, 0]); |
| 1516 | /// ``` |
| 1517 | fn positions<P>(self, predicate: P) -> Positions<Self, P> |
| 1518 | where Self: Sized, |
| 1519 | P: FnMut(Self::Item) -> bool, |
| 1520 | { |
| 1521 | adaptors::positions(self, predicate) |
| 1522 | } |
| 1523 | |
| 1524 | /// Return an iterator adaptor that applies a mutating function |
| 1525 | /// to each element before yielding it. |
| 1526 | /// |
| 1527 | /// ``` |
| 1528 | /// use itertools::Itertools; |
| 1529 | /// |
| 1530 | /// let input = vec![vec![1], vec![3, 2, 1]]; |
| 1531 | /// let it = input.into_iter().update(|mut v| v.push(0)); |
| 1532 | /// itertools::assert_equal(it, vec![vec![1, 0], vec![3, 2, 1, 0]]); |
| 1533 | /// ``` |
| 1534 | fn update<F>(self, updater: F) -> Update<Self, F> |
| 1535 | where Self: Sized, |
| 1536 | F: FnMut(&mut Self::Item), |
| 1537 | { |
| 1538 | adaptors::update(self, updater) |
| 1539 | } |
| 1540 | |
| 1541 | // non-adaptor methods |
| 1542 | /// Advances the iterator and returns the next items grouped in a tuple of |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1543 | /// a specific size (up to 12). |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1544 | /// |
| 1545 | /// If there are enough elements to be grouped in a tuple, then the tuple is |
| 1546 | /// returned inside `Some`, otherwise `None` is returned. |
| 1547 | /// |
| 1548 | /// ``` |
| 1549 | /// use itertools::Itertools; |
| 1550 | /// |
| 1551 | /// let mut iter = 1..5; |
| 1552 | /// |
| 1553 | /// assert_eq!(Some((1, 2)), iter.next_tuple()); |
| 1554 | /// ``` |
| 1555 | fn next_tuple<T>(&mut self) -> Option<T> |
| 1556 | where Self: Sized + Iterator<Item = T::Item>, |
| 1557 | T: traits::HomogeneousTuple |
| 1558 | { |
| 1559 | T::collect_from_iter_no_buf(self) |
| 1560 | } |
| 1561 | |
| 1562 | /// Collects all items from the iterator into a tuple of a specific size |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1563 | /// (up to 12). |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1564 | /// |
| 1565 | /// If the number of elements inside the iterator is **exactly** equal to |
| 1566 | /// the tuple size, then the tuple is returned inside `Some`, otherwise |
| 1567 | /// `None` is returned. |
| 1568 | /// |
| 1569 | /// ``` |
| 1570 | /// use itertools::Itertools; |
| 1571 | /// |
| 1572 | /// let iter = 1..3; |
| 1573 | /// |
| 1574 | /// if let Some((x, y)) = iter.collect_tuple() { |
| 1575 | /// assert_eq!((x, y), (1, 2)) |
| 1576 | /// } else { |
| 1577 | /// panic!("Expected two elements") |
| 1578 | /// } |
| 1579 | /// ``` |
| 1580 | fn collect_tuple<T>(mut self) -> Option<T> |
| 1581 | where Self: Sized + Iterator<Item = T::Item>, |
| 1582 | T: traits::HomogeneousTuple |
| 1583 | { |
| 1584 | match self.next_tuple() { |
| 1585 | elt @ Some(_) => match self.next() { |
| 1586 | Some(_) => None, |
| 1587 | None => elt, |
| 1588 | }, |
| 1589 | _ => None |
| 1590 | } |
| 1591 | } |
| 1592 | |
| 1593 | |
| 1594 | /// Find the position and value of the first element satisfying a predicate. |
| 1595 | /// |
| 1596 | /// The iterator is not advanced past the first element found. |
| 1597 | /// |
| 1598 | /// ``` |
| 1599 | /// use itertools::Itertools; |
| 1600 | /// |
| 1601 | /// let text = "Hα"; |
| 1602 | /// assert_eq!(text.chars().find_position(|ch| ch.is_lowercase()), Some((1, 'α'))); |
| 1603 | /// ``` |
| 1604 | fn find_position<P>(&mut self, mut pred: P) -> Option<(usize, Self::Item)> |
| 1605 | where P: FnMut(&Self::Item) -> bool |
| 1606 | { |
| 1607 | let mut index = 0usize; |
| 1608 | for elt in self { |
| 1609 | if pred(&elt) { |
| 1610 | return Some((index, elt)); |
| 1611 | } |
| 1612 | index += 1; |
| 1613 | } |
| 1614 | None |
| 1615 | } |
| 1616 | |
| 1617 | /// Check whether all elements compare equal. |
| 1618 | /// |
| 1619 | /// Empty iterators are considered to have equal elements: |
| 1620 | /// |
| 1621 | /// ``` |
| 1622 | /// use itertools::Itertools; |
| 1623 | /// |
| 1624 | /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; |
| 1625 | /// assert!(!data.iter().all_equal()); |
| 1626 | /// assert!(data[0..3].iter().all_equal()); |
| 1627 | /// assert!(data[3..5].iter().all_equal()); |
| 1628 | /// assert!(data[5..8].iter().all_equal()); |
| 1629 | /// |
| 1630 | /// let data : Option<usize> = None; |
| 1631 | /// assert!(data.into_iter().all_equal()); |
| 1632 | /// ``` |
| 1633 | fn all_equal(&mut self) -> bool |
| 1634 | where Self: Sized, |
| 1635 | Self::Item: PartialEq, |
| 1636 | { |
| 1637 | match self.next() { |
| 1638 | None => true, |
| 1639 | Some(a) => self.all(|x| a == x), |
| 1640 | } |
| 1641 | } |
| 1642 | |
| 1643 | /// Consume the first `n` elements from the iterator eagerly, |
| 1644 | /// and return the same iterator again. |
| 1645 | /// |
| 1646 | /// It works similarly to *.skip(* `n` *)* except it is eager and |
| 1647 | /// preserves the iterator type. |
| 1648 | /// |
| 1649 | /// ``` |
| 1650 | /// use itertools::Itertools; |
| 1651 | /// |
| 1652 | /// let mut iter = "αβγ".chars().dropping(2); |
| 1653 | /// itertools::assert_equal(iter, "γ".chars()); |
| 1654 | /// ``` |
| 1655 | /// |
| 1656 | /// *Fusing notes: if the iterator is exhausted by dropping, |
| 1657 | /// the result of calling `.next()` again depends on the iterator implementation.* |
| 1658 | fn dropping(mut self, n: usize) -> Self |
| 1659 | where Self: Sized |
| 1660 | { |
| 1661 | if n > 0 { |
| 1662 | self.nth(n - 1); |
| 1663 | } |
| 1664 | self |
| 1665 | } |
| 1666 | |
| 1667 | /// Consume the last `n` elements from the iterator eagerly, |
| 1668 | /// and return the same iterator again. |
| 1669 | /// |
| 1670 | /// This is only possible on double ended iterators. `n` may be |
| 1671 | /// larger than the number of elements. |
| 1672 | /// |
| 1673 | /// Note: This method is eager, dropping the back elements immediately and |
| 1674 | /// preserves the iterator type. |
| 1675 | /// |
| 1676 | /// ``` |
| 1677 | /// use itertools::Itertools; |
| 1678 | /// |
| 1679 | /// let init = vec![0, 3, 6, 9].into_iter().dropping_back(1); |
| 1680 | /// itertools::assert_equal(init, vec![0, 3, 6]); |
| 1681 | /// ``` |
| 1682 | fn dropping_back(mut self, n: usize) -> Self |
| 1683 | where Self: Sized, |
| 1684 | Self: DoubleEndedIterator |
| 1685 | { |
| 1686 | if n > 0 { |
| 1687 | (&mut self).rev().nth(n - 1); |
| 1688 | } |
| 1689 | self |
| 1690 | } |
| 1691 | |
| 1692 | /// Run the closure `f` eagerly on each element of the iterator. |
| 1693 | /// |
| 1694 | /// Consumes the iterator until its end. |
| 1695 | /// |
| 1696 | /// ``` |
| 1697 | /// use std::sync::mpsc::channel; |
| 1698 | /// use itertools::Itertools; |
| 1699 | /// |
| 1700 | /// let (tx, rx) = channel(); |
| 1701 | /// |
| 1702 | /// // use .foreach() to apply a function to each value -- sending it |
| 1703 | /// (0..5).map(|x| x * 2 + 1).foreach(|x| { tx.send(x).unwrap(); } ); |
| 1704 | /// |
| 1705 | /// drop(tx); |
| 1706 | /// |
| 1707 | /// itertools::assert_equal(rx.iter(), vec![1, 3, 5, 7, 9]); |
| 1708 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1709 | #[deprecated(note="Use .for_each() instead", since="0.8.0")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1710 | fn foreach<F>(self, f: F) |
| 1711 | where F: FnMut(Self::Item), |
| 1712 | Self: Sized, |
| 1713 | { |
| 1714 | self.for_each(f) |
| 1715 | } |
| 1716 | |
| 1717 | /// Combine all an iterator's elements into one element by using `Extend`. |
| 1718 | /// |
| 1719 | /// This combinator will extend the first item with each of the rest of the |
| 1720 | /// items of the iterator. If the iterator is empty, the default value of |
| 1721 | /// `I::Item` is returned. |
| 1722 | /// |
| 1723 | /// ```rust |
| 1724 | /// use itertools::Itertools; |
| 1725 | /// |
| 1726 | /// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; |
| 1727 | /// assert_eq!(input.into_iter().concat(), |
| 1728 | /// vec![1, 2, 3, 4, 5, 6]); |
| 1729 | /// ``` |
| 1730 | fn concat(self) -> Self::Item |
| 1731 | where Self: Sized, |
| 1732 | Self::Item: Extend<<<Self as Iterator>::Item as IntoIterator>::Item> + IntoIterator + Default |
| 1733 | { |
| 1734 | concat(self) |
| 1735 | } |
| 1736 | |
| 1737 | /// `.collect_vec()` is simply a type specialization of `.collect()`, |
| 1738 | /// for convenience. |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1739 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1740 | fn collect_vec(self) -> Vec<Self::Item> |
| 1741 | where Self: Sized |
| 1742 | { |
| 1743 | self.collect() |
| 1744 | } |
| 1745 | |
| 1746 | /// `.try_collect()` is more convenient way of writing |
| 1747 | /// `.collect::<Result<_, _>>()` |
| 1748 | /// |
| 1749 | /// # Example |
| 1750 | /// |
| 1751 | /// ``` |
| 1752 | /// use std::{fs, io}; |
| 1753 | /// use itertools::Itertools; |
| 1754 | /// |
| 1755 | /// fn process_dir_entries(entries: &[fs::DirEntry]) { |
| 1756 | /// // ... |
| 1757 | /// } |
| 1758 | /// |
| 1759 | /// fn do_stuff() -> std::io::Result<()> { |
| 1760 | /// let entries: Vec<_> = fs::read_dir(".")?.try_collect()?; |
| 1761 | /// process_dir_entries(&entries); |
| 1762 | /// |
| 1763 | /// Ok(()) |
| 1764 | /// } |
| 1765 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1766 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1767 | fn try_collect<T, U, E>(self) -> Result<U, E> |
| 1768 | where |
| 1769 | Self: Sized + Iterator<Item = Result<T, E>>, |
| 1770 | Result<U, E>: FromIterator<Result<T, E>>, |
| 1771 | { |
| 1772 | self.collect() |
| 1773 | } |
| 1774 | |
| 1775 | /// Assign to each reference in `self` from the `from` iterator, |
| 1776 | /// stopping at the shortest of the two iterators. |
| 1777 | /// |
| 1778 | /// The `from` iterator is queried for its next element before the `self` |
| 1779 | /// iterator, and if either is exhausted the method is done. |
| 1780 | /// |
| 1781 | /// Return the number of elements written. |
| 1782 | /// |
| 1783 | /// ``` |
| 1784 | /// use itertools::Itertools; |
| 1785 | /// |
| 1786 | /// let mut xs = [0; 4]; |
| 1787 | /// xs.iter_mut().set_from(1..); |
| 1788 | /// assert_eq!(xs, [1, 2, 3, 4]); |
| 1789 | /// ``` |
| 1790 | #[inline] |
| 1791 | fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize |
| 1792 | where Self: Iterator<Item = &'a mut A>, |
| 1793 | J: IntoIterator<Item = A> |
| 1794 | { |
| 1795 | let mut count = 0; |
| 1796 | for elt in from { |
| 1797 | match self.next() { |
| 1798 | None => break, |
| 1799 | Some(ptr) => *ptr = elt, |
| 1800 | } |
| 1801 | count += 1; |
| 1802 | } |
| 1803 | count |
| 1804 | } |
| 1805 | |
| 1806 | /// Combine all iterator elements into one String, separated by `sep`. |
| 1807 | /// |
| 1808 | /// Use the `Display` implementation of each element. |
| 1809 | /// |
| 1810 | /// ``` |
| 1811 | /// use itertools::Itertools; |
| 1812 | /// |
| 1813 | /// assert_eq!(["a", "b", "c"].iter().join(", "), "a, b, c"); |
| 1814 | /// assert_eq!([1, 2, 3].iter().join(", "), "1, 2, 3"); |
| 1815 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1816 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1817 | fn join(&mut self, sep: &str) -> String |
| 1818 | where Self::Item: std::fmt::Display |
| 1819 | { |
| 1820 | match self.next() { |
| 1821 | None => String::new(), |
| 1822 | Some(first_elt) => { |
| 1823 | // estimate lower bound of capacity needed |
| 1824 | let (lower, _) = self.size_hint(); |
| 1825 | let mut result = String::with_capacity(sep.len() * lower); |
| 1826 | write!(&mut result, "{}", first_elt).unwrap(); |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1827 | self.for_each(|elt| { |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1828 | result.push_str(sep); |
| 1829 | write!(&mut result, "{}", elt).unwrap(); |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1830 | }); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1831 | result |
| 1832 | } |
| 1833 | } |
| 1834 | } |
| 1835 | |
| 1836 | /// Format all iterator elements, separated by `sep`. |
| 1837 | /// |
| 1838 | /// All elements are formatted (any formatting trait) |
| 1839 | /// with `sep` inserted between each element. |
| 1840 | /// |
| 1841 | /// **Panics** if the formatter helper is formatted more than once. |
| 1842 | /// |
| 1843 | /// ``` |
| 1844 | /// use itertools::Itertools; |
| 1845 | /// |
| 1846 | /// let data = [1.1, 2.71828, -3.]; |
| 1847 | /// assert_eq!( |
| 1848 | /// format!("{:.2}", data.iter().format(", ")), |
| 1849 | /// "1.10, 2.72, -3.00"); |
| 1850 | /// ``` |
| 1851 | fn format(self, sep: &str) -> Format<Self> |
| 1852 | where Self: Sized, |
| 1853 | { |
| 1854 | format::new_format_default(self, sep) |
| 1855 | } |
| 1856 | |
| 1857 | /// Format all iterator elements, separated by `sep`. |
| 1858 | /// |
| 1859 | /// This is a customizable version of `.format()`. |
| 1860 | /// |
| 1861 | /// The supplied closure `format` is called once per iterator element, |
| 1862 | /// with two arguments: the element and a callback that takes a |
| 1863 | /// `&Display` value, i.e. any reference to type that implements `Display`. |
| 1864 | /// |
| 1865 | /// Using `&format_args!(...)` is the most versatile way to apply custom |
| 1866 | /// element formatting. The callback can be called multiple times if needed. |
| 1867 | /// |
| 1868 | /// **Panics** if the formatter helper is formatted more than once. |
| 1869 | /// |
| 1870 | /// ``` |
| 1871 | /// use itertools::Itertools; |
| 1872 | /// |
| 1873 | /// let data = [1.1, 2.71828, -3.]; |
| 1874 | /// let data_formatter = data.iter().format_with(", ", |elt, f| f(&format_args!("{:.2}", elt))); |
| 1875 | /// assert_eq!(format!("{}", data_formatter), |
| 1876 | /// "1.10, 2.72, -3.00"); |
| 1877 | /// |
| 1878 | /// // .format_with() is recursively composable |
| 1879 | /// let matrix = [[1., 2., 3.], |
| 1880 | /// [4., 5., 6.]]; |
| 1881 | /// let matrix_formatter = matrix.iter().format_with("\n", |row, f| { |
| 1882 | /// f(&row.iter().format_with(", ", |elt, g| g(&elt))) |
| 1883 | /// }); |
| 1884 | /// assert_eq!(format!("{}", matrix_formatter), |
| 1885 | /// "1, 2, 3\n4, 5, 6"); |
| 1886 | /// |
| 1887 | /// |
| 1888 | /// ``` |
| 1889 | fn format_with<F>(self, sep: &str, format: F) -> FormatWith<Self, F> |
| 1890 | where Self: Sized, |
| 1891 | F: FnMut(Self::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, |
| 1892 | { |
| 1893 | format::new_format(self, sep, format) |
| 1894 | } |
| 1895 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1896 | /// See [`.fold_ok()`](#method.fold_ok). |
| 1897 | #[deprecated(note="Use .fold_ok() instead", since="0.10.0")] |
| 1898 | fn fold_results<A, E, B, F>(&mut self, start: B, f: F) -> Result<B, E> |
| 1899 | where Self: Iterator<Item = Result<A, E>>, |
| 1900 | F: FnMut(B, A) -> B |
| 1901 | { |
| 1902 | self.fold_ok(start, f) |
| 1903 | } |
| 1904 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1905 | /// Fold `Result` values from an iterator. |
| 1906 | /// |
| 1907 | /// Only `Ok` values are folded. If no error is encountered, the folded |
| 1908 | /// value is returned inside `Ok`. Otherwise, the operation terminates |
| 1909 | /// and returns the first `Err` value it encounters. No iterator elements are |
| 1910 | /// consumed after the first error. |
| 1911 | /// |
| 1912 | /// The first accumulator value is the `start` parameter. |
| 1913 | /// Each iteration passes the accumulator value and the next value inside `Ok` |
| 1914 | /// to the fold function `f` and its return value becomes the new accumulator value. |
| 1915 | /// |
| 1916 | /// For example the sequence *Ok(1), Ok(2), Ok(3)* will result in a |
| 1917 | /// computation like this: |
| 1918 | /// |
| 1919 | /// ```ignore |
| 1920 | /// let mut accum = start; |
| 1921 | /// accum = f(accum, 1); |
| 1922 | /// accum = f(accum, 2); |
| 1923 | /// accum = f(accum, 3); |
| 1924 | /// ``` |
| 1925 | /// |
| 1926 | /// With a `start` value of 0 and an addition as folding function, |
| 1927 | /// this effectively results in *((0 + 1) + 2) + 3* |
| 1928 | /// |
| 1929 | /// ``` |
| 1930 | /// use std::ops::Add; |
| 1931 | /// use itertools::Itertools; |
| 1932 | /// |
| 1933 | /// let values = [1, 2, -2, -1, 2, 1]; |
| 1934 | /// assert_eq!( |
| 1935 | /// values.iter() |
| 1936 | /// .map(Ok::<_, ()>) |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1937 | /// .fold_ok(0, Add::add), |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1938 | /// Ok(3) |
| 1939 | /// ); |
| 1940 | /// assert!( |
| 1941 | /// values.iter() |
| 1942 | /// .map(|&x| if x >= 0 { Ok(x) } else { Err("Negative number") }) |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1943 | /// .fold_ok(0, Add::add) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1944 | /// .is_err() |
| 1945 | /// ); |
| 1946 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1947 | fn fold_ok<A, E, B, F>(&mut self, mut start: B, mut f: F) -> Result<B, E> |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1948 | where Self: Iterator<Item = Result<A, E>>, |
| 1949 | F: FnMut(B, A) -> B |
| 1950 | { |
| 1951 | for elt in self { |
| 1952 | match elt { |
| 1953 | Ok(v) => start = f(start, v), |
| 1954 | Err(u) => return Err(u), |
| 1955 | } |
| 1956 | } |
| 1957 | Ok(start) |
| 1958 | } |
| 1959 | |
| 1960 | /// Fold `Option` values from an iterator. |
| 1961 | /// |
| 1962 | /// Only `Some` values are folded. If no `None` is encountered, the folded |
| 1963 | /// value is returned inside `Some`. Otherwise, the operation terminates |
| 1964 | /// and returns `None`. No iterator elements are consumed after the `None`. |
| 1965 | /// |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1966 | /// This is the `Option` equivalent to `fold_ok`. |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 1967 | /// |
| 1968 | /// ``` |
| 1969 | /// use std::ops::Add; |
| 1970 | /// use itertools::Itertools; |
| 1971 | /// |
| 1972 | /// let mut values = vec![Some(1), Some(2), Some(-2)].into_iter(); |
| 1973 | /// assert_eq!(values.fold_options(5, Add::add), Some(5 + 1 + 2 - 2)); |
| 1974 | /// |
| 1975 | /// let mut more_values = vec![Some(2), None, Some(0)].into_iter(); |
| 1976 | /// assert!(more_values.fold_options(0, Add::add).is_none()); |
| 1977 | /// assert_eq!(more_values.next().unwrap(), Some(0)); |
| 1978 | /// ``` |
| 1979 | fn fold_options<A, B, F>(&mut self, mut start: B, mut f: F) -> Option<B> |
| 1980 | where Self: Iterator<Item = Option<A>>, |
| 1981 | F: FnMut(B, A) -> B |
| 1982 | { |
| 1983 | for elt in self { |
| 1984 | match elt { |
| 1985 | Some(v) => start = f(start, v), |
| 1986 | None => return None, |
| 1987 | } |
| 1988 | } |
| 1989 | Some(start) |
| 1990 | } |
| 1991 | |
| 1992 | /// Accumulator of the elements in the iterator. |
| 1993 | /// |
| 1994 | /// Like `.fold()`, without a base case. If the iterator is |
| 1995 | /// empty, return `None`. With just one element, return it. |
| 1996 | /// Otherwise elements are accumulated in sequence using the closure `f`. |
| 1997 | /// |
| 1998 | /// ``` |
| 1999 | /// use itertools::Itertools; |
| 2000 | /// |
| 2001 | /// assert_eq!((0..10).fold1(|x, y| x + y).unwrap_or(0), 45); |
| 2002 | /// assert_eq!((0..0).fold1(|x, y| x * y), None); |
| 2003 | /// ``` |
| 2004 | fn fold1<F>(mut self, f: F) -> Option<Self::Item> |
| 2005 | where F: FnMut(Self::Item, Self::Item) -> Self::Item, |
| 2006 | Self: Sized, |
| 2007 | { |
| 2008 | self.next().map(move |x| self.fold(x, f)) |
| 2009 | } |
| 2010 | |
| 2011 | /// Accumulate the elements in the iterator in a tree-like manner. |
| 2012 | /// |
| 2013 | /// You can think of it as, while there's more than one item, repeatedly |
| 2014 | /// combining adjacent items. It does so in bottom-up-merge-sort order, |
| 2015 | /// however, so that it needs only logarithmic stack space. |
| 2016 | /// |
| 2017 | /// This produces a call tree like the following (where the calls under |
| 2018 | /// an item are done after reading that item): |
| 2019 | /// |
| 2020 | /// ```text |
| 2021 | /// 1 2 3 4 5 6 7 |
| 2022 | /// │ │ │ │ │ │ │ |
| 2023 | /// └─f └─f └─f │ |
| 2024 | /// │ │ │ │ |
| 2025 | /// └───f └─f |
| 2026 | /// │ │ |
| 2027 | /// └─────f |
| 2028 | /// ``` |
| 2029 | /// |
| 2030 | /// Which, for non-associative functions, will typically produce a different |
| 2031 | /// result than the linear call tree used by `fold1`: |
| 2032 | /// |
| 2033 | /// ```text |
| 2034 | /// 1 2 3 4 5 6 7 |
| 2035 | /// │ │ │ │ │ │ │ |
| 2036 | /// └─f─f─f─f─f─f |
| 2037 | /// ``` |
| 2038 | /// |
| 2039 | /// If `f` is associative, prefer the normal `fold1` instead. |
| 2040 | /// |
| 2041 | /// ``` |
| 2042 | /// use itertools::Itertools; |
| 2043 | /// |
| 2044 | /// // The same tree as above |
| 2045 | /// let num_strings = (1..8).map(|x| x.to_string()); |
| 2046 | /// assert_eq!(num_strings.tree_fold1(|x, y| format!("f({}, {})", x, y)), |
| 2047 | /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); |
| 2048 | /// |
| 2049 | /// // Like fold1, an empty iterator produces None |
| 2050 | /// assert_eq!((0..0).tree_fold1(|x, y| x * y), None); |
| 2051 | /// |
| 2052 | /// // tree_fold1 matches fold1 for associative operations... |
| 2053 | /// assert_eq!((0..10).tree_fold1(|x, y| x + y), |
| 2054 | /// (0..10).fold1(|x, y| x + y)); |
| 2055 | /// // ...but not for non-associative ones |
| 2056 | /// assert_ne!((0..10).tree_fold1(|x, y| x - y), |
| 2057 | /// (0..10).fold1(|x, y| x - y)); |
| 2058 | /// ``` |
| 2059 | fn tree_fold1<F>(mut self, mut f: F) -> Option<Self::Item> |
| 2060 | where F: FnMut(Self::Item, Self::Item) -> Self::Item, |
| 2061 | Self: Sized, |
| 2062 | { |
| 2063 | type State<T> = Result<T, Option<T>>; |
| 2064 | |
| 2065 | fn inner0<T, II, FF>(it: &mut II, f: &mut FF) -> State<T> |
| 2066 | where |
| 2067 | II: Iterator<Item = T>, |
| 2068 | FF: FnMut(T, T) -> T |
| 2069 | { |
| 2070 | // This function could be replaced with `it.next().ok_or(None)`, |
| 2071 | // but half the useful tree_fold1 work is combining adjacent items, |
| 2072 | // so put that in a form that LLVM is more likely to optimize well. |
| 2073 | |
| 2074 | let a = |
| 2075 | if let Some(v) = it.next() { v } |
| 2076 | else { return Err(None) }; |
| 2077 | let b = |
| 2078 | if let Some(v) = it.next() { v } |
| 2079 | else { return Err(Some(a)) }; |
| 2080 | Ok(f(a, b)) |
| 2081 | } |
| 2082 | |
| 2083 | fn inner<T, II, FF>(stop: usize, it: &mut II, f: &mut FF) -> State<T> |
| 2084 | where |
| 2085 | II: Iterator<Item = T>, |
| 2086 | FF: FnMut(T, T) -> T |
| 2087 | { |
| 2088 | let mut x = inner0(it, f)?; |
| 2089 | for height in 0..stop { |
| 2090 | // Try to get another tree the same size with which to combine it, |
| 2091 | // creating a new tree that's twice as big for next time around. |
| 2092 | let next = |
| 2093 | if height == 0 { |
| 2094 | inner0(it, f) |
| 2095 | } else { |
| 2096 | inner(height, it, f) |
| 2097 | }; |
| 2098 | match next { |
| 2099 | Ok(y) => x = f(x, y), |
| 2100 | |
| 2101 | // If we ran out of items, combine whatever we did manage |
| 2102 | // to get. It's better combined with the current value |
| 2103 | // than something in a parent frame, because the tree in |
| 2104 | // the parent is always as least as big as this one. |
| 2105 | Err(None) => return Err(Some(x)), |
| 2106 | Err(Some(y)) => return Err(Some(f(x, y))), |
| 2107 | } |
| 2108 | } |
| 2109 | Ok(x) |
| 2110 | } |
| 2111 | |
| 2112 | match inner(usize::max_value(), &mut self, &mut f) { |
| 2113 | Err(x) => x, |
| 2114 | _ => unreachable!(), |
| 2115 | } |
| 2116 | } |
| 2117 | |
| 2118 | /// An iterator method that applies a function, producing a single, final value. |
| 2119 | /// |
| 2120 | /// `fold_while()` is basically equivalent to `fold()` but with additional support for |
| 2121 | /// early exit via short-circuiting. |
| 2122 | /// |
| 2123 | /// ``` |
| 2124 | /// use itertools::Itertools; |
| 2125 | /// use itertools::FoldWhile::{Continue, Done}; |
| 2126 | /// |
| 2127 | /// let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; |
| 2128 | /// |
| 2129 | /// let mut result = 0; |
| 2130 | /// |
| 2131 | /// // for loop: |
| 2132 | /// for i in &numbers { |
| 2133 | /// if *i > 5 { |
| 2134 | /// break; |
| 2135 | /// } |
| 2136 | /// result = result + i; |
| 2137 | /// } |
| 2138 | /// |
| 2139 | /// // fold: |
| 2140 | /// let result2 = numbers.iter().fold(0, |acc, x| { |
| 2141 | /// if *x > 5 { acc } else { acc + x } |
| 2142 | /// }); |
| 2143 | /// |
| 2144 | /// // fold_while: |
| 2145 | /// let result3 = numbers.iter().fold_while(0, |acc, x| { |
| 2146 | /// if *x > 5 { Done(acc) } else { Continue(acc + x) } |
| 2147 | /// }).into_inner(); |
| 2148 | /// |
| 2149 | /// // they're the same |
| 2150 | /// assert_eq!(result, result2); |
| 2151 | /// assert_eq!(result2, result3); |
| 2152 | /// ``` |
| 2153 | /// |
| 2154 | /// The big difference between the computations of `result2` and `result3` is that while |
| 2155 | /// `fold()` called the provided closure for every item of the callee iterator, |
| 2156 | /// `fold_while()` actually stopped iterating as soon as it encountered `Fold::Done(_)`. |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2157 | fn fold_while<B, F>(&mut self, init: B, mut f: F) -> FoldWhile<B> |
| 2158 | where Self: Sized, |
| 2159 | F: FnMut(B, Self::Item) -> FoldWhile<B> |
| 2160 | { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2161 | use Result::{ |
| 2162 | Ok as Continue, |
| 2163 | Err as Break, |
| 2164 | }; |
| 2165 | |
| 2166 | let result = self.try_fold(init, #[inline(always)] |acc, v| |
| 2167 | match f(acc, v) { |
| 2168 | FoldWhile::Continue(acc) => Continue(acc), |
| 2169 | FoldWhile::Done(acc) => Break(acc), |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2170 | } |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2171 | ); |
| 2172 | |
| 2173 | match result { |
| 2174 | Continue(acc) => FoldWhile::Continue(acc), |
| 2175 | Break(acc) => FoldWhile::Done(acc), |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2176 | } |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2177 | } |
| 2178 | |
| 2179 | /// Iterate over the entire iterator and add all the elements. |
| 2180 | /// |
| 2181 | /// An empty iterator returns `None`, otherwise `Some(sum)`. |
| 2182 | /// |
| 2183 | /// # Panics |
| 2184 | /// |
| 2185 | /// When calling `sum1()` and a primitive integer type is being returned, this |
| 2186 | /// method will panic if the computation overflows and debug assertions are |
| 2187 | /// enabled. |
| 2188 | /// |
| 2189 | /// # Examples |
| 2190 | /// |
| 2191 | /// ``` |
| 2192 | /// use itertools::Itertools; |
| 2193 | /// |
| 2194 | /// let empty_sum = (1..1).sum1::<i32>(); |
| 2195 | /// assert_eq!(empty_sum, None); |
| 2196 | /// |
| 2197 | /// let nonempty_sum = (1..11).sum1::<i32>(); |
| 2198 | /// assert_eq!(nonempty_sum, Some(55)); |
| 2199 | /// ``` |
| 2200 | fn sum1<S>(mut self) -> Option<S> |
| 2201 | where Self: Sized, |
| 2202 | S: std::iter::Sum<Self::Item>, |
| 2203 | { |
| 2204 | self.next() |
| 2205 | .map(|first| once(first).chain(self).sum()) |
| 2206 | } |
| 2207 | |
| 2208 | /// Iterate over the entire iterator and multiply all the elements. |
| 2209 | /// |
| 2210 | /// An empty iterator returns `None`, otherwise `Some(product)`. |
| 2211 | /// |
| 2212 | /// # Panics |
| 2213 | /// |
| 2214 | /// When calling `product1()` and a primitive integer type is being returned, |
| 2215 | /// method will panic if the computation overflows and debug assertions are |
| 2216 | /// enabled. |
| 2217 | /// |
| 2218 | /// # Examples |
| 2219 | /// ``` |
| 2220 | /// use itertools::Itertools; |
| 2221 | /// |
| 2222 | /// let empty_product = (1..1).product1::<i32>(); |
| 2223 | /// assert_eq!(empty_product, None); |
| 2224 | /// |
| 2225 | /// let nonempty_product = (1..11).product1::<i32>(); |
| 2226 | /// assert_eq!(nonempty_product, Some(3628800)); |
| 2227 | /// ``` |
| 2228 | fn product1<P>(mut self) -> Option<P> |
| 2229 | where Self: Sized, |
| 2230 | P: std::iter::Product<Self::Item>, |
| 2231 | { |
| 2232 | self.next() |
| 2233 | .map(|first| once(first).chain(self).product()) |
| 2234 | } |
| 2235 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2236 | /// Sort all iterator elements into a new iterator in ascending order. |
| 2237 | /// |
| 2238 | /// **Note:** This consumes the entire iterator, uses the |
| 2239 | /// `slice::sort_unstable()` method and returns the result as a new |
| 2240 | /// iterator that owns its elements. |
| 2241 | /// |
| 2242 | /// The sorted iterator, if directly collected to a `Vec`, is converted |
| 2243 | /// without any extra copying or allocation cost. |
| 2244 | /// |
| 2245 | /// ``` |
| 2246 | /// use itertools::Itertools; |
| 2247 | /// |
| 2248 | /// // sort the letters of the text in ascending order |
| 2249 | /// let text = "bdacfe"; |
| 2250 | /// itertools::assert_equal(text.chars().sorted_unstable(), |
| 2251 | /// "abcdef".chars()); |
| 2252 | /// ``` |
| 2253 | #[cfg(feature = "use_alloc")] |
| 2254 | fn sorted_unstable(self) -> VecIntoIter<Self::Item> |
| 2255 | where Self: Sized, |
| 2256 | Self::Item: Ord |
| 2257 | { |
| 2258 | // Use .sort_unstable() directly since it is not quite identical with |
| 2259 | // .sort_by(Ord::cmp) |
| 2260 | let mut v = Vec::from_iter(self); |
| 2261 | v.sort_unstable(); |
| 2262 | v.into_iter() |
| 2263 | } |
| 2264 | |
| 2265 | /// Sort all iterator elements into a new iterator in ascending order. |
| 2266 | /// |
| 2267 | /// **Note:** This consumes the entire iterator, uses the |
| 2268 | /// `slice::sort_unstable_by()` method and returns the result as a new |
| 2269 | /// iterator that owns its elements. |
| 2270 | /// |
| 2271 | /// The sorted iterator, if directly collected to a `Vec`, is converted |
| 2272 | /// without any extra copying or allocation cost. |
| 2273 | /// |
| 2274 | /// ``` |
| 2275 | /// use itertools::Itertools; |
| 2276 | /// |
| 2277 | /// // sort people in descending order by age |
| 2278 | /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; |
| 2279 | /// |
| 2280 | /// let oldest_people_first = people |
| 2281 | /// .into_iter() |
| 2282 | /// .sorted_unstable_by(|a, b| Ord::cmp(&b.1, &a.1)) |
| 2283 | /// .map(|(person, _age)| person); |
| 2284 | /// |
| 2285 | /// itertools::assert_equal(oldest_people_first, |
| 2286 | /// vec!["Jill", "Jack", "Jane", "John"]); |
| 2287 | /// ``` |
| 2288 | #[cfg(feature = "use_alloc")] |
| 2289 | fn sorted_unstable_by<F>(self, cmp: F) -> VecIntoIter<Self::Item> |
| 2290 | where Self: Sized, |
| 2291 | F: FnMut(&Self::Item, &Self::Item) -> Ordering, |
| 2292 | { |
| 2293 | let mut v = Vec::from_iter(self); |
| 2294 | v.sort_unstable_by(cmp); |
| 2295 | v.into_iter() |
| 2296 | } |
| 2297 | |
| 2298 | /// Sort all iterator elements into a new iterator in ascending order. |
| 2299 | /// |
| 2300 | /// **Note:** This consumes the entire iterator, uses the |
| 2301 | /// `slice::sort_unstable_by_key()` method and returns the result as a new |
| 2302 | /// iterator that owns its elements. |
| 2303 | /// |
| 2304 | /// The sorted iterator, if directly collected to a `Vec`, is converted |
| 2305 | /// without any extra copying or allocation cost. |
| 2306 | /// |
| 2307 | /// ``` |
| 2308 | /// use itertools::Itertools; |
| 2309 | /// |
| 2310 | /// // sort people in descending order by age |
| 2311 | /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; |
| 2312 | /// |
| 2313 | /// let oldest_people_first = people |
| 2314 | /// .into_iter() |
| 2315 | /// .sorted_unstable_by_key(|x| -x.1) |
| 2316 | /// .map(|(person, _age)| person); |
| 2317 | /// |
| 2318 | /// itertools::assert_equal(oldest_people_first, |
| 2319 | /// vec!["Jill", "Jack", "Jane", "John"]); |
| 2320 | /// ``` |
| 2321 | #[cfg(feature = "use_alloc")] |
| 2322 | fn sorted_unstable_by_key<K, F>(self, f: F) -> VecIntoIter<Self::Item> |
| 2323 | where Self: Sized, |
| 2324 | K: Ord, |
| 2325 | F: FnMut(&Self::Item) -> K, |
| 2326 | { |
| 2327 | let mut v = Vec::from_iter(self); |
| 2328 | v.sort_unstable_by_key(f); |
| 2329 | v.into_iter() |
| 2330 | } |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2331 | |
| 2332 | /// Sort all iterator elements into a new iterator in ascending order. |
| 2333 | /// |
| 2334 | /// **Note:** This consumes the entire iterator, uses the |
| 2335 | /// `slice::sort()` method and returns the result as a new |
| 2336 | /// iterator that owns its elements. |
| 2337 | /// |
| 2338 | /// The sorted iterator, if directly collected to a `Vec`, is converted |
| 2339 | /// without any extra copying or allocation cost. |
| 2340 | /// |
| 2341 | /// ``` |
| 2342 | /// use itertools::Itertools; |
| 2343 | /// |
| 2344 | /// // sort the letters of the text in ascending order |
| 2345 | /// let text = "bdacfe"; |
| 2346 | /// itertools::assert_equal(text.chars().sorted(), |
| 2347 | /// "abcdef".chars()); |
| 2348 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2349 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2350 | fn sorted(self) -> VecIntoIter<Self::Item> |
| 2351 | where Self: Sized, |
| 2352 | Self::Item: Ord |
| 2353 | { |
| 2354 | // Use .sort() directly since it is not quite identical with |
| 2355 | // .sort_by(Ord::cmp) |
| 2356 | let mut v = Vec::from_iter(self); |
| 2357 | v.sort(); |
| 2358 | v.into_iter() |
| 2359 | } |
| 2360 | |
| 2361 | /// Sort all iterator elements into a new iterator in ascending order. |
| 2362 | /// |
| 2363 | /// **Note:** This consumes the entire iterator, uses the |
| 2364 | /// `slice::sort_by()` method and returns the result as a new |
| 2365 | /// iterator that owns its elements. |
| 2366 | /// |
| 2367 | /// The sorted iterator, if directly collected to a `Vec`, is converted |
| 2368 | /// without any extra copying or allocation cost. |
| 2369 | /// |
| 2370 | /// ``` |
| 2371 | /// use itertools::Itertools; |
| 2372 | /// |
| 2373 | /// // sort people in descending order by age |
| 2374 | /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; |
| 2375 | /// |
| 2376 | /// let oldest_people_first = people |
| 2377 | /// .into_iter() |
| 2378 | /// .sorted_by(|a, b| Ord::cmp(&b.1, &a.1)) |
| 2379 | /// .map(|(person, _age)| person); |
| 2380 | /// |
| 2381 | /// itertools::assert_equal(oldest_people_first, |
| 2382 | /// vec!["Jill", "Jack", "Jane", "John"]); |
| 2383 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2384 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2385 | fn sorted_by<F>(self, cmp: F) -> VecIntoIter<Self::Item> |
| 2386 | where Self: Sized, |
| 2387 | F: FnMut(&Self::Item, &Self::Item) -> Ordering, |
| 2388 | { |
| 2389 | let mut v = Vec::from_iter(self); |
| 2390 | v.sort_by(cmp); |
| 2391 | v.into_iter() |
| 2392 | } |
| 2393 | |
| 2394 | /// Sort all iterator elements into a new iterator in ascending order. |
| 2395 | /// |
| 2396 | /// **Note:** This consumes the entire iterator, uses the |
| 2397 | /// `slice::sort_by_key()` method and returns the result as a new |
| 2398 | /// iterator that owns its elements. |
| 2399 | /// |
| 2400 | /// The sorted iterator, if directly collected to a `Vec`, is converted |
| 2401 | /// without any extra copying or allocation cost. |
| 2402 | /// |
| 2403 | /// ``` |
| 2404 | /// use itertools::Itertools; |
| 2405 | /// |
| 2406 | /// // sort people in descending order by age |
| 2407 | /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; |
| 2408 | /// |
| 2409 | /// let oldest_people_first = people |
| 2410 | /// .into_iter() |
| 2411 | /// .sorted_by_key(|x| -x.1) |
| 2412 | /// .map(|(person, _age)| person); |
| 2413 | /// |
| 2414 | /// itertools::assert_equal(oldest_people_first, |
| 2415 | /// vec!["Jill", "Jack", "Jane", "John"]); |
| 2416 | /// ``` |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2417 | #[cfg(feature = "use_alloc")] |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2418 | fn sorted_by_key<K, F>(self, f: F) -> VecIntoIter<Self::Item> |
| 2419 | where Self: Sized, |
| 2420 | K: Ord, |
| 2421 | F: FnMut(&Self::Item) -> K, |
| 2422 | { |
| 2423 | let mut v = Vec::from_iter(self); |
| 2424 | v.sort_by_key(f); |
| 2425 | v.into_iter() |
| 2426 | } |
| 2427 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2428 | /// Sort the k smallest elements into a new iterator, in ascending order. |
| 2429 | /// |
| 2430 | /// **Note:** This consumes the entire iterator, and returns the result |
| 2431 | /// as a new iterator that owns its elements. If the input contains |
| 2432 | /// less than k elements, the result is equivalent to `self.sorted()`. |
| 2433 | /// |
| 2434 | /// This is guaranteed to use `k * sizeof(Self::Item) + O(1)` memory |
| 2435 | /// and `O(n log k)` time, with `n` the number of elements in the input. |
| 2436 | /// |
| 2437 | /// The sorted iterator, if directly collected to a `Vec`, is converted |
| 2438 | /// without any extra copying or allocation cost. |
| 2439 | /// |
| 2440 | /// **Note:** This is functionally-equivalent to `self.sorted().take(k)` |
| 2441 | /// but much more efficient. |
| 2442 | /// |
| 2443 | /// ``` |
| 2444 | /// use itertools::Itertools; |
| 2445 | /// |
| 2446 | /// // A random permutation of 0..15 |
| 2447 | /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; |
| 2448 | /// |
| 2449 | /// let five_smallest = numbers |
| 2450 | /// .into_iter() |
| 2451 | /// .k_smallest(5); |
| 2452 | /// |
| 2453 | /// itertools::assert_equal(five_smallest, 0..5); |
| 2454 | /// ``` |
| 2455 | #[cfg(feature = "use_alloc")] |
| 2456 | fn k_smallest(self, k: usize) -> VecIntoIter<Self::Item> |
| 2457 | where Self: Sized, |
| 2458 | Self::Item: Ord |
| 2459 | { |
| 2460 | crate::k_smallest::k_smallest(self, k) |
| 2461 | .into_sorted_vec() |
| 2462 | .into_iter() |
| 2463 | } |
| 2464 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2465 | /// Collect all iterator elements into one of two |
| 2466 | /// partitions. Unlike `Iterator::partition`, each partition may |
| 2467 | /// have a distinct type. |
| 2468 | /// |
| 2469 | /// ``` |
| 2470 | /// use itertools::{Itertools, Either}; |
| 2471 | /// |
| 2472 | /// let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)]; |
| 2473 | /// |
| 2474 | /// let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures |
| 2475 | /// .into_iter() |
| 2476 | /// .partition_map(|r| { |
| 2477 | /// match r { |
| 2478 | /// Ok(v) => Either::Left(v), |
| 2479 | /// Err(v) => Either::Right(v), |
| 2480 | /// } |
| 2481 | /// }); |
| 2482 | /// |
| 2483 | /// assert_eq!(successes, [1, 2]); |
| 2484 | /// assert_eq!(failures, [false, true]); |
| 2485 | /// ``` |
| 2486 | fn partition_map<A, B, F, L, R>(self, mut predicate: F) -> (A, B) |
| 2487 | where Self: Sized, |
| 2488 | F: FnMut(Self::Item) -> Either<L, R>, |
| 2489 | A: Default + Extend<L>, |
| 2490 | B: Default + Extend<R>, |
| 2491 | { |
| 2492 | let mut left = A::default(); |
| 2493 | let mut right = B::default(); |
| 2494 | |
| 2495 | self.for_each(|val| match predicate(val) { |
| 2496 | Either::Left(v) => left.extend(Some(v)), |
| 2497 | Either::Right(v) => right.extend(Some(v)), |
| 2498 | }); |
| 2499 | |
| 2500 | (left, right) |
| 2501 | } |
| 2502 | |
| 2503 | /// Return a `HashMap` of keys mapped to `Vec`s of values. Keys and values |
| 2504 | /// are taken from `(Key, Value)` tuple pairs yielded by the input iterator. |
| 2505 | /// |
| 2506 | /// ``` |
| 2507 | /// use itertools::Itertools; |
| 2508 | /// |
| 2509 | /// let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)]; |
| 2510 | /// let lookup = data.into_iter().into_group_map(); |
| 2511 | /// |
| 2512 | /// assert_eq!(lookup[&0], vec![10, 20]); |
| 2513 | /// assert_eq!(lookup.get(&1), None); |
| 2514 | /// assert_eq!(lookup[&2], vec![12, 42]); |
| 2515 | /// assert_eq!(lookup[&3], vec![13, 33]); |
| 2516 | /// ``` |
| 2517 | #[cfg(feature = "use_std")] |
| 2518 | fn into_group_map<K, V>(self) -> HashMap<K, Vec<V>> |
| 2519 | where Self: Iterator<Item=(K, V)> + Sized, |
| 2520 | K: Hash + Eq, |
| 2521 | { |
| 2522 | group_map::into_group_map(self) |
| 2523 | } |
| 2524 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 2525 | /// Return an `Iterator` on a HahMap. Keys mapped to `Vec`s of values. The key is specified in |
| 2526 | /// in the closure. |
| 2527 | /// Different of into_group_map_by because the key is still present. It is also more general. |
| 2528 | /// you can also fold the group_map. |
| 2529 | /// |
| 2530 | /// ``` |
| 2531 | /// use itertools::Itertools; |
| 2532 | /// use std::collections::HashMap; |
| 2533 | /// |
| 2534 | /// let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)]; |
| 2535 | /// let lookup: HashMap<u32,Vec<(u32, u32)>> = data.clone().into_iter().into_group_map_by(|a| |
| 2536 | /// a.0); |
| 2537 | /// |
| 2538 | /// assert_eq!(lookup[&0], vec![(0,10),(0,20)]); |
| 2539 | /// assert_eq!(lookup.get(&1), None); |
| 2540 | /// assert_eq!(lookup[&2], vec![(2,12), (2,42)]); |
| 2541 | /// assert_eq!(lookup[&3], vec![(3,13), (3,33)]); |
| 2542 | /// |
| 2543 | /// assert_eq!( |
| 2544 | /// data.into_iter() |
| 2545 | /// .into_group_map_by(|x| x.0) |
| 2546 | /// .into_iter() |
| 2547 | /// .map(|(key, values)| (key, values.into_iter().fold(0,|acc, (_,v)| acc + v ))) |
| 2548 | /// .collect::<HashMap<u32,u32>>()[&0], 30) |
| 2549 | /// ``` |
| 2550 | #[cfg(feature = "use_std")] |
| 2551 | fn into_group_map_by<K, V, F>(self, f: F) -> HashMap<K, Vec<V>> |
| 2552 | where |
| 2553 | Self: Iterator<Item=V> + Sized, |
| 2554 | K: Hash + Eq, |
| 2555 | F: Fn(&V) -> K, |
| 2556 | { |
| 2557 | group_map::into_group_map_by(self, f) |
| 2558 | } |
| 2559 | |
| 2560 | /// Constructs a `GroupingMap` to be used later with one of the efficient |
| 2561 | /// group-and-fold operations it allows to perform. |
| 2562 | /// |
| 2563 | /// The input iterator must yield item in the form of `(K, V)` where the |
| 2564 | /// value of type `K` will be used as key to identify the groups and the |
| 2565 | /// value of type `V` as value for the folding operation. |
| 2566 | /// |
| 2567 | /// See [`GroupingMap`](./structs/struct.GroupingMap.html) for more informations |
| 2568 | /// on what operations are available. |
| 2569 | #[cfg(feature = "use_std")] |
| 2570 | fn into_grouping_map<K, V>(self) -> GroupingMap<Self> |
| 2571 | where Self: Iterator<Item=(K, V)> + Sized, |
| 2572 | K: Hash + Eq, |
| 2573 | { |
| 2574 | grouping_map::new(self) |
| 2575 | } |
| 2576 | |
| 2577 | /// Constructs a `GroupingMap` to be used later with one of the efficient |
| 2578 | /// group-and-fold operations it allows to perform. |
| 2579 | /// |
| 2580 | /// The values from this iterator will be used as values for the folding operation |
| 2581 | /// while the keys will be obtained from the values by calling `key_mapper`. |
| 2582 | /// |
| 2583 | /// See [`GroupingMap`](./structs/struct.GroupingMap.html) for more informations |
| 2584 | /// on what operations are available. |
| 2585 | #[cfg(feature = "use_std")] |
| 2586 | fn into_grouping_map_by<K, V, F>(self, key_mapper: F) -> GroupingMapBy<Self, F> |
| 2587 | where Self: Iterator<Item=V> + Sized, |
| 2588 | K: Hash + Eq, |
| 2589 | F: FnMut(&V) -> K |
| 2590 | { |
| 2591 | grouping_map::new(grouping_map::MapForGrouping::new(self, key_mapper)) |
| 2592 | } |
| 2593 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2594 | /// Return the minimum and maximum elements in the iterator. |
| 2595 | /// |
| 2596 | /// The return type `MinMaxResult` is an enum of three variants: |
| 2597 | /// |
| 2598 | /// - `NoElements` if the iterator is empty. |
| 2599 | /// - `OneElement(x)` if the iterator has exactly one element. |
| 2600 | /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two |
| 2601 | /// values are equal if and only if there is more than one |
| 2602 | /// element in the iterator and all elements are equal. |
| 2603 | /// |
| 2604 | /// On an iterator of length `n`, `minmax` does `1.5 * n` comparisons, |
| 2605 | /// and so is faster than calling `min` and `max` separately which does |
| 2606 | /// `2 * n` comparisons. |
| 2607 | /// |
| 2608 | /// # Examples |
| 2609 | /// |
| 2610 | /// ``` |
| 2611 | /// use itertools::Itertools; |
| 2612 | /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; |
| 2613 | /// |
| 2614 | /// let a: [i32; 0] = []; |
| 2615 | /// assert_eq!(a.iter().minmax(), NoElements); |
| 2616 | /// |
| 2617 | /// let a = [1]; |
| 2618 | /// assert_eq!(a.iter().minmax(), OneElement(&1)); |
| 2619 | /// |
| 2620 | /// let a = [1, 2, 3, 4, 5]; |
| 2621 | /// assert_eq!(a.iter().minmax(), MinMax(&1, &5)); |
| 2622 | /// |
| 2623 | /// let a = [1, 1, 1, 1]; |
| 2624 | /// assert_eq!(a.iter().minmax(), MinMax(&1, &1)); |
| 2625 | /// ``` |
| 2626 | /// |
| 2627 | /// The elements can be floats but no particular result is guaranteed |
| 2628 | /// if an element is NaN. |
| 2629 | fn minmax(self) -> MinMaxResult<Self::Item> |
| 2630 | where Self: Sized, Self::Item: PartialOrd |
| 2631 | { |
| 2632 | minmax::minmax_impl(self, |_| (), |x, y, _, _| x < y) |
| 2633 | } |
| 2634 | |
| 2635 | /// Return the minimum and maximum element of an iterator, as determined by |
| 2636 | /// the specified function. |
| 2637 | /// |
| 2638 | /// The return value is a variant of `MinMaxResult` like for `minmax()`. |
| 2639 | /// |
| 2640 | /// For the minimum, the first minimal element is returned. For the maximum, |
| 2641 | /// the last maximal element wins. This matches the behavior of the standard |
| 2642 | /// `Iterator::min()` and `Iterator::max()` methods. |
| 2643 | /// |
| 2644 | /// The keys can be floats but no particular result is guaranteed |
| 2645 | /// if a key is NaN. |
| 2646 | fn minmax_by_key<K, F>(self, key: F) -> MinMaxResult<Self::Item> |
| 2647 | where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K |
| 2648 | { |
| 2649 | minmax::minmax_impl(self, key, |_, _, xk, yk| xk < yk) |
| 2650 | } |
| 2651 | |
| 2652 | /// Return the minimum and maximum element of an iterator, as determined by |
| 2653 | /// the specified comparison function. |
| 2654 | /// |
| 2655 | /// The return value is a variant of `MinMaxResult` like for `minmax()`. |
| 2656 | /// |
| 2657 | /// For the minimum, the first minimal element is returned. For the maximum, |
| 2658 | /// the last maximal element wins. This matches the behavior of the standard |
| 2659 | /// `Iterator::min()` and `Iterator::max()` methods. |
| 2660 | fn minmax_by<F>(self, mut compare: F) -> MinMaxResult<Self::Item> |
| 2661 | where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering |
| 2662 | { |
| 2663 | minmax::minmax_impl( |
| 2664 | self, |
| 2665 | |_| (), |
| 2666 | |x, y, _, _| Ordering::Less == compare(x, y) |
| 2667 | ) |
| 2668 | } |
| 2669 | |
| 2670 | /// Return the position of the maximum element in the iterator. |
| 2671 | /// |
| 2672 | /// If several elements are equally maximum, the position of the |
| 2673 | /// last of them is returned. |
| 2674 | /// |
| 2675 | /// # Examples |
| 2676 | /// |
| 2677 | /// ``` |
| 2678 | /// use itertools::Itertools; |
| 2679 | /// |
| 2680 | /// let a: [i32; 0] = []; |
| 2681 | /// assert_eq!(a.iter().position_max(), None); |
| 2682 | /// |
| 2683 | /// let a = [-3, 0, 1, 5, -10]; |
| 2684 | /// assert_eq!(a.iter().position_max(), Some(3)); |
| 2685 | /// |
| 2686 | /// let a = [1, 1, -1, -1]; |
| 2687 | /// assert_eq!(a.iter().position_max(), Some(1)); |
| 2688 | /// ``` |
| 2689 | fn position_max(self) -> Option<usize> |
| 2690 | where Self: Sized, Self::Item: Ord |
| 2691 | { |
| 2692 | self.enumerate() |
| 2693 | .max_by(|x, y| Ord::cmp(&x.1, &y.1)) |
| 2694 | .map(|x| x.0) |
| 2695 | } |
| 2696 | |
| 2697 | /// Return the position of the maximum element in the iterator, as |
| 2698 | /// determined by the specified function. |
| 2699 | /// |
| 2700 | /// If several elements are equally maximum, the position of the |
| 2701 | /// last of them is returned. |
| 2702 | /// |
| 2703 | /// # Examples |
| 2704 | /// |
| 2705 | /// ``` |
| 2706 | /// use itertools::Itertools; |
| 2707 | /// |
| 2708 | /// let a: [i32; 0] = []; |
| 2709 | /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), None); |
| 2710 | /// |
| 2711 | /// let a = [-3_i32, 0, 1, 5, -10]; |
| 2712 | /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(4)); |
| 2713 | /// |
| 2714 | /// let a = [1_i32, 1, -1, -1]; |
| 2715 | /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(3)); |
| 2716 | /// ``` |
| 2717 | fn position_max_by_key<K, F>(self, mut key: F) -> Option<usize> |
| 2718 | where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K |
| 2719 | { |
| 2720 | self.enumerate() |
| 2721 | .max_by(|x, y| Ord::cmp(&key(&x.1), &key(&y.1))) |
| 2722 | .map(|x| x.0) |
| 2723 | } |
| 2724 | |
| 2725 | /// Return the position of the maximum element in the iterator, as |
| 2726 | /// determined by the specified comparison function. |
| 2727 | /// |
| 2728 | /// If several elements are equally maximum, the position of the |
| 2729 | /// last of them is returned. |
| 2730 | /// |
| 2731 | /// # Examples |
| 2732 | /// |
| 2733 | /// ``` |
| 2734 | /// use itertools::Itertools; |
| 2735 | /// |
| 2736 | /// let a: [i32; 0] = []; |
| 2737 | /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), None); |
| 2738 | /// |
| 2739 | /// let a = [-3_i32, 0, 1, 5, -10]; |
| 2740 | /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(3)); |
| 2741 | /// |
| 2742 | /// let a = [1_i32, 1, -1, -1]; |
| 2743 | /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(1)); |
| 2744 | /// ``` |
| 2745 | fn position_max_by<F>(self, mut compare: F) -> Option<usize> |
| 2746 | where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering |
| 2747 | { |
| 2748 | self.enumerate() |
| 2749 | .max_by(|x, y| compare(&x.1, &y.1)) |
| 2750 | .map(|x| x.0) |
| 2751 | } |
| 2752 | |
| 2753 | /// Return the position of the minimum element in the iterator. |
| 2754 | /// |
| 2755 | /// If several elements are equally minimum, the position of the |
| 2756 | /// first of them is returned. |
| 2757 | /// |
| 2758 | /// # Examples |
| 2759 | /// |
| 2760 | /// ``` |
| 2761 | /// use itertools::Itertools; |
| 2762 | /// |
| 2763 | /// let a: [i32; 0] = []; |
| 2764 | /// assert_eq!(a.iter().position_min(), None); |
| 2765 | /// |
| 2766 | /// let a = [-3, 0, 1, 5, -10]; |
| 2767 | /// assert_eq!(a.iter().position_min(), Some(4)); |
| 2768 | /// |
| 2769 | /// let a = [1, 1, -1, -1]; |
| 2770 | /// assert_eq!(a.iter().position_min(), Some(2)); |
| 2771 | /// ``` |
| 2772 | fn position_min(self) -> Option<usize> |
| 2773 | where Self: Sized, Self::Item: Ord |
| 2774 | { |
| 2775 | self.enumerate() |
| 2776 | .min_by(|x, y| Ord::cmp(&x.1, &y.1)) |
| 2777 | .map(|x| x.0) |
| 2778 | } |
| 2779 | |
| 2780 | /// Return the position of the minimum element in the iterator, as |
| 2781 | /// determined by the specified function. |
| 2782 | /// |
| 2783 | /// If several elements are equally minimum, the position of the |
| 2784 | /// first of them is returned. |
| 2785 | /// |
| 2786 | /// # Examples |
| 2787 | /// |
| 2788 | /// ``` |
| 2789 | /// use itertools::Itertools; |
| 2790 | /// |
| 2791 | /// let a: [i32; 0] = []; |
| 2792 | /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), None); |
| 2793 | /// |
| 2794 | /// let a = [-3_i32, 0, 1, 5, -10]; |
| 2795 | /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(1)); |
| 2796 | /// |
| 2797 | /// let a = [1_i32, 1, -1, -1]; |
| 2798 | /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(0)); |
| 2799 | /// ``` |
| 2800 | fn position_min_by_key<K, F>(self, mut key: F) -> Option<usize> |
| 2801 | where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K |
| 2802 | { |
| 2803 | self.enumerate() |
| 2804 | .min_by(|x, y| Ord::cmp(&key(&x.1), &key(&y.1))) |
| 2805 | .map(|x| x.0) |
| 2806 | } |
| 2807 | |
| 2808 | /// Return the position of the minimum element in the iterator, as |
| 2809 | /// determined by the specified comparison function. |
| 2810 | /// |
| 2811 | /// If several elements are equally minimum, the position of the |
| 2812 | /// first of them is returned. |
| 2813 | /// |
| 2814 | /// # Examples |
| 2815 | /// |
| 2816 | /// ``` |
| 2817 | /// use itertools::Itertools; |
| 2818 | /// |
| 2819 | /// let a: [i32; 0] = []; |
| 2820 | /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), None); |
| 2821 | /// |
| 2822 | /// let a = [-3_i32, 0, 1, 5, -10]; |
| 2823 | /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(4)); |
| 2824 | /// |
| 2825 | /// let a = [1_i32, 1, -1, -1]; |
| 2826 | /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(2)); |
| 2827 | /// ``` |
| 2828 | fn position_min_by<F>(self, mut compare: F) -> Option<usize> |
| 2829 | where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering |
| 2830 | { |
| 2831 | self.enumerate() |
| 2832 | .min_by(|x, y| compare(&x.1, &y.1)) |
| 2833 | .map(|x| x.0) |
| 2834 | } |
| 2835 | |
| 2836 | /// Return the positions of the minimum and maximum elements in |
| 2837 | /// the iterator. |
| 2838 | /// |
| 2839 | /// The return type [`MinMaxResult`] is an enum of three variants: |
| 2840 | /// |
| 2841 | /// - `NoElements` if the iterator is empty. |
| 2842 | /// - `OneElement(xpos)` if the iterator has exactly one element. |
| 2843 | /// - `MinMax(xpos, ypos)` is returned otherwise, where the |
| 2844 | /// element at `xpos` ≤ the element at `ypos`. While the |
| 2845 | /// referenced elements themselves may be equal, `xpos` cannot |
| 2846 | /// be equal to `ypos`. |
| 2847 | /// |
| 2848 | /// On an iterator of length `n`, `position_minmax` does `1.5 * n` |
| 2849 | /// comparisons, and so is faster than calling `positon_min` and |
| 2850 | /// `position_max` separately which does `2 * n` comparisons. |
| 2851 | /// |
| 2852 | /// For the minimum, if several elements are equally minimum, the |
| 2853 | /// position of the first of them is returned. For the maximum, if |
| 2854 | /// several elements are equally maximum, the position of the last |
| 2855 | /// of them is returned. |
| 2856 | /// |
| 2857 | /// The elements can be floats but no particular result is |
| 2858 | /// guaranteed if an element is NaN. |
| 2859 | /// |
| 2860 | /// # Examples |
| 2861 | /// |
| 2862 | /// ``` |
| 2863 | /// use itertools::Itertools; |
| 2864 | /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; |
| 2865 | /// |
| 2866 | /// let a: [i32; 0] = []; |
| 2867 | /// assert_eq!(a.iter().position_minmax(), NoElements); |
| 2868 | /// |
| 2869 | /// let a = [10]; |
| 2870 | /// assert_eq!(a.iter().position_minmax(), OneElement(0)); |
| 2871 | /// |
| 2872 | /// let a = [-3, 0, 1, 5, -10]; |
| 2873 | /// assert_eq!(a.iter().position_minmax(), MinMax(4, 3)); |
| 2874 | /// |
| 2875 | /// let a = [1, 1, -1, -1]; |
| 2876 | /// assert_eq!(a.iter().position_minmax(), MinMax(2, 1)); |
| 2877 | /// ``` |
| 2878 | /// |
| 2879 | /// [`MinMaxResult`]: enum.MinMaxResult.html |
| 2880 | fn position_minmax(self) -> MinMaxResult<usize> |
| 2881 | where Self: Sized, Self::Item: PartialOrd |
| 2882 | { |
| 2883 | use crate::MinMaxResult::{NoElements, OneElement, MinMax}; |
| 2884 | match minmax::minmax_impl(self.enumerate(), |_| (), |x, y, _, _| x.1 < y.1) { |
| 2885 | NoElements => NoElements, |
| 2886 | OneElement(x) => OneElement(x.0), |
| 2887 | MinMax(x, y) => MinMax(x.0, y.0), |
| 2888 | } |
| 2889 | } |
| 2890 | |
| 2891 | /// Return the postions of the minimum and maximum elements of an |
| 2892 | /// iterator, as determined by the specified function. |
| 2893 | /// |
| 2894 | /// The return value is a variant of [`MinMaxResult`] like for |
| 2895 | /// [`position_minmax`]. |
| 2896 | /// |
| 2897 | /// For the minimum, if several elements are equally minimum, the |
| 2898 | /// position of the first of them is returned. For the maximum, if |
| 2899 | /// several elements are equally maximum, the position of the last |
| 2900 | /// of them is returned. |
| 2901 | /// |
| 2902 | /// The keys can be floats but no particular result is guaranteed |
| 2903 | /// if a key is NaN. |
| 2904 | /// |
| 2905 | /// # Examples |
| 2906 | /// |
| 2907 | /// ``` |
| 2908 | /// use itertools::Itertools; |
| 2909 | /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; |
| 2910 | /// |
| 2911 | /// let a: [i32; 0] = []; |
| 2912 | /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), NoElements); |
| 2913 | /// |
| 2914 | /// let a = [10_i32]; |
| 2915 | /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), OneElement(0)); |
| 2916 | /// |
| 2917 | /// let a = [-3_i32, 0, 1, 5, -10]; |
| 2918 | /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(1, 4)); |
| 2919 | /// |
| 2920 | /// let a = [1_i32, 1, -1, -1]; |
| 2921 | /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(0, 3)); |
| 2922 | /// ``` |
| 2923 | /// |
| 2924 | /// [`MinMaxResult`]: enum.MinMaxResult.html |
| 2925 | /// [`position_minmax`]: #method.position_minmax |
| 2926 | fn position_minmax_by_key<K, F>(self, mut key: F) -> MinMaxResult<usize> |
| 2927 | where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K |
| 2928 | { |
| 2929 | use crate::MinMaxResult::{NoElements, OneElement, MinMax}; |
| 2930 | match self.enumerate().minmax_by_key(|e| key(&e.1)) { |
| 2931 | NoElements => NoElements, |
| 2932 | OneElement(x) => OneElement(x.0), |
| 2933 | MinMax(x, y) => MinMax(x.0, y.0), |
| 2934 | } |
| 2935 | } |
| 2936 | |
| 2937 | /// Return the postions of the minimum and maximum elements of an |
| 2938 | /// iterator, as determined by the specified comparison function. |
| 2939 | /// |
| 2940 | /// The return value is a variant of [`MinMaxResult`] like for |
| 2941 | /// [`position_minmax`]. |
| 2942 | /// |
| 2943 | /// For the minimum, if several elements are equally minimum, the |
| 2944 | /// position of the first of them is returned. For the maximum, if |
| 2945 | /// several elements are equally maximum, the position of the last |
| 2946 | /// of them is returned. |
| 2947 | /// |
| 2948 | /// # Examples |
| 2949 | /// |
| 2950 | /// ``` |
| 2951 | /// use itertools::Itertools; |
| 2952 | /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; |
| 2953 | /// |
| 2954 | /// let a: [i32; 0] = []; |
| 2955 | /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), NoElements); |
| 2956 | /// |
| 2957 | /// let a = [10_i32]; |
| 2958 | /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), OneElement(0)); |
| 2959 | /// |
| 2960 | /// let a = [-3_i32, 0, 1, 5, -10]; |
| 2961 | /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(4, 3)); |
| 2962 | /// |
| 2963 | /// let a = [1_i32, 1, -1, -1]; |
| 2964 | /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(2, 1)); |
| 2965 | /// ``` |
| 2966 | /// |
| 2967 | /// [`MinMaxResult`]: enum.MinMaxResult.html |
| 2968 | /// [`position_minmax`]: #method.position_minmax |
| 2969 | fn position_minmax_by<F>(self, mut compare: F) -> MinMaxResult<usize> |
| 2970 | where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering |
| 2971 | { |
| 2972 | use crate::MinMaxResult::{NoElements, OneElement, MinMax}; |
| 2973 | match self.enumerate().minmax_by(|x, y| compare(&x.1, &y.1)) { |
| 2974 | NoElements => NoElements, |
| 2975 | OneElement(x) => OneElement(x.0), |
| 2976 | MinMax(x, y) => MinMax(x.0, y.0), |
| 2977 | } |
| 2978 | } |
| 2979 | |
| 2980 | /// If the iterator yields exactly one element, that element will be returned, otherwise |
| 2981 | /// an error will be returned containing an iterator that has the same output as the input |
| 2982 | /// iterator. |
| 2983 | /// |
| 2984 | /// This provides an additional layer of validation over just calling `Iterator::next()`. |
| 2985 | /// If your assumption that there should only be one element yielded is false this provides |
| 2986 | /// the opportunity to detect and handle that, preventing errors at a distance. |
| 2987 | /// |
| 2988 | /// # Examples |
| 2989 | /// ``` |
| 2990 | /// use itertools::Itertools; |
| 2991 | /// |
| 2992 | /// assert_eq!((0..10).filter(|&x| x == 2).exactly_one().unwrap(), 2); |
| 2993 | /// assert!((0..10).filter(|&x| x > 1 && x < 4).exactly_one().unwrap_err().eq(2..4)); |
| 2994 | /// assert!((0..10).filter(|&x| x > 1 && x < 5).exactly_one().unwrap_err().eq(2..5)); |
| 2995 | /// assert!((0..10).filter(|&_| false).exactly_one().unwrap_err().eq(0..0)); |
| 2996 | /// ``` |
| 2997 | fn exactly_one(mut self) -> Result<Self::Item, ExactlyOneError<Self>> |
| 2998 | where |
| 2999 | Self: Sized, |
| 3000 | { |
| 3001 | match self.next() { |
| 3002 | Some(first) => { |
| 3003 | match self.next() { |
| 3004 | Some(second) => { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 3005 | Err(ExactlyOneError::new(Some(Either::Left([first, second])), self)) |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 3006 | } |
| 3007 | None => { |
| 3008 | Ok(first) |
| 3009 | } |
| 3010 | } |
| 3011 | } |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 3012 | None => Err(ExactlyOneError::new(None, self)), |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 3013 | } |
| 3014 | } |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 3015 | |
| 3016 | /// An iterator adaptor that allows the user to peek at multiple `.next()` |
| 3017 | /// values without advancing the base iterator. |
| 3018 | /// |
| 3019 | /// # Examples |
| 3020 | /// ``` |
| 3021 | /// use itertools::Itertools; |
| 3022 | /// |
| 3023 | /// let mut iter = (0..10).multipeek(); |
| 3024 | /// assert_eq!(iter.peek(), Some(&0)); |
| 3025 | /// assert_eq!(iter.peek(), Some(&1)); |
| 3026 | /// assert_eq!(iter.peek(), Some(&2)); |
| 3027 | /// assert_eq!(iter.next(), Some(0)); |
| 3028 | /// assert_eq!(iter.peek(), Some(&1)); |
| 3029 | /// ``` |
| 3030 | #[cfg(feature = "use_alloc")] |
| 3031 | fn multipeek(self) -> MultiPeek<Self> |
| 3032 | where |
| 3033 | Self: Sized, |
| 3034 | { |
| 3035 | multipeek_impl::multipeek(self) |
| 3036 | } |
| 3037 | |
| 3038 | /// Collect the items in this iterator and return a `HashMap` which |
| 3039 | /// contains each item that appears in the iterator and the number |
| 3040 | /// of times it appears. |
| 3041 | /// |
| 3042 | /// # Examples |
| 3043 | /// ``` |
| 3044 | /// # use itertools::Itertools; |
| 3045 | /// let counts = [1, 1, 1, 3, 3, 5].into_iter().counts(); |
| 3046 | /// assert_eq!(counts[&1], 3); |
| 3047 | /// assert_eq!(counts[&3], 2); |
| 3048 | /// assert_eq!(counts[&5], 1); |
| 3049 | /// assert_eq!(counts.get(&0), None); |
| 3050 | /// ``` |
| 3051 | #[cfg(feature = "use_std")] |
| 3052 | fn counts(self) -> HashMap<Self::Item, usize> |
| 3053 | where |
| 3054 | Self: Sized, |
| 3055 | Self::Item: Eq + Hash, |
| 3056 | { |
| 3057 | let mut counts = HashMap::new(); |
| 3058 | self.for_each(|item| *counts.entry(item).or_default() += 1); |
| 3059 | counts |
| 3060 | } |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 3061 | } |
| 3062 | |
| 3063 | impl<T: ?Sized> Itertools for T where T: Iterator { } |
| 3064 | |
| 3065 | /// Return `true` if both iterables produce equal sequences |
| 3066 | /// (elements pairwise equal and sequences of the same length), |
| 3067 | /// `false` otherwise. |
| 3068 | /// |
| 3069 | /// This is an `IntoIterator` enabled function that is similar to the standard |
| 3070 | /// library method `Iterator::eq`. |
| 3071 | /// |
| 3072 | /// ``` |
| 3073 | /// assert!(itertools::equal(vec![1, 2, 3], 1..4)); |
| 3074 | /// assert!(!itertools::equal(&[0, 0], &[0, 0, 0])); |
| 3075 | /// ``` |
| 3076 | pub fn equal<I, J>(a: I, b: J) -> bool |
| 3077 | where I: IntoIterator, |
| 3078 | J: IntoIterator, |
| 3079 | I::Item: PartialEq<J::Item> |
| 3080 | { |
| 3081 | let mut ia = a.into_iter(); |
| 3082 | let mut ib = b.into_iter(); |
| 3083 | loop { |
| 3084 | match ia.next() { |
| 3085 | Some(x) => match ib.next() { |
| 3086 | Some(y) => if x != y { return false; }, |
| 3087 | None => return false, |
| 3088 | }, |
| 3089 | None => return ib.next().is_none() |
| 3090 | } |
| 3091 | } |
| 3092 | } |
| 3093 | |
| 3094 | /// Assert that two iterables produce equal sequences, with the same |
| 3095 | /// semantics as *equal(a, b)*. |
| 3096 | /// |
| 3097 | /// **Panics** on assertion failure with a message that shows the |
| 3098 | /// two iteration elements. |
| 3099 | /// |
| 3100 | /// ```ignore |
| 3101 | /// assert_equal("exceed".split('c'), "excess".split('c')); |
| 3102 | /// // ^PANIC: panicked at 'Failed assertion Some("eed") == Some("ess") for iteration 1', |
| 3103 | /// ``` |
| 3104 | pub fn assert_equal<I, J>(a: I, b: J) |
| 3105 | where I: IntoIterator, |
| 3106 | J: IntoIterator, |
| 3107 | I::Item: fmt::Debug + PartialEq<J::Item>, |
| 3108 | J::Item: fmt::Debug, |
| 3109 | { |
| 3110 | let mut ia = a.into_iter(); |
| 3111 | let mut ib = b.into_iter(); |
| 3112 | let mut i = 0; |
| 3113 | loop { |
| 3114 | match (ia.next(), ib.next()) { |
| 3115 | (None, None) => return, |
| 3116 | (a, b) => { |
| 3117 | let equal = match (&a, &b) { |
| 3118 | (&Some(ref a), &Some(ref b)) => a == b, |
| 3119 | _ => false, |
| 3120 | }; |
| 3121 | assert!(equal, "Failed assertion {a:?} == {b:?} for iteration {i}", |
| 3122 | i=i, a=a, b=b); |
| 3123 | i += 1; |
| 3124 | } |
| 3125 | } |
| 3126 | } |
| 3127 | } |
| 3128 | |
| 3129 | /// Partition a sequence using predicate `pred` so that elements |
| 3130 | /// that map to `true` are placed before elements which map to `false`. |
| 3131 | /// |
| 3132 | /// The order within the partitions is arbitrary. |
| 3133 | /// |
| 3134 | /// Return the index of the split point. |
| 3135 | /// |
| 3136 | /// ``` |
| 3137 | /// use itertools::partition; |
| 3138 | /// |
| 3139 | /// # // use repeated numbers to not promise any ordering |
| 3140 | /// let mut data = [7, 1, 1, 7, 1, 1, 7]; |
| 3141 | /// let split_index = partition(&mut data, |elt| *elt >= 3); |
| 3142 | /// |
| 3143 | /// assert_eq!(data, [7, 7, 7, 1, 1, 1, 1]); |
| 3144 | /// assert_eq!(split_index, 3); |
| 3145 | /// ``` |
| 3146 | pub fn partition<'a, A: 'a, I, F>(iter: I, mut pred: F) -> usize |
| 3147 | where I: IntoIterator<Item = &'a mut A>, |
| 3148 | I::IntoIter: DoubleEndedIterator, |
| 3149 | F: FnMut(&A) -> bool |
| 3150 | { |
| 3151 | let mut split_index = 0; |
| 3152 | let mut iter = iter.into_iter(); |
| 3153 | 'main: while let Some(front) = iter.next() { |
| 3154 | if !pred(front) { |
| 3155 | loop { |
| 3156 | match iter.next_back() { |
| 3157 | Some(back) => if pred(back) { |
| 3158 | std::mem::swap(front, back); |
| 3159 | break; |
| 3160 | }, |
| 3161 | None => break 'main, |
| 3162 | } |
| 3163 | } |
| 3164 | } |
| 3165 | split_index += 1; |
| 3166 | } |
| 3167 | split_index |
| 3168 | } |
| 3169 | |
| 3170 | /// An enum used for controlling the execution of `.fold_while()`. |
| 3171 | /// |
| 3172 | /// See [`.fold_while()`](trait.Itertools.html#method.fold_while) for more information. |
| 3173 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
| 3174 | pub enum FoldWhile<T> { |
| 3175 | /// Continue folding with this value |
| 3176 | Continue(T), |
| 3177 | /// Fold is complete and will return this value |
| 3178 | Done(T), |
| 3179 | } |
| 3180 | |
| 3181 | impl<T> FoldWhile<T> { |
| 3182 | /// Return the value in the continue or done. |
| 3183 | pub fn into_inner(self) -> T { |
| 3184 | match self { |
| 3185 | FoldWhile::Continue(x) | FoldWhile::Done(x) => x, |
| 3186 | } |
| 3187 | } |
| 3188 | |
| 3189 | /// Return true if `self` is `Done`, false if it is `Continue`. |
| 3190 | pub fn is_done(&self) -> bool { |
| 3191 | match *self { |
| 3192 | FoldWhile::Continue(_) => false, |
| 3193 | FoldWhile::Done(_) => true, |
| 3194 | } |
| 3195 | } |
| 3196 | } |