1//! Free functions that create iterator adaptors or call iterator methods.
2//!
3//! The benefit of free functions is that they accept any [`IntoIterator`] as
4//! argument, so the resulting code may be easier to read.
5
6#[cfg(feature = "use_alloc")]
7use std::fmt::Display;
8use std::iter::{self, Zip};
9#[cfg(feature = "use_alloc")]
10type VecIntoIter<T> = alloc::vec::IntoIter<T>;
11
12#[cfg(feature = "use_alloc")]
13use alloc::{
14 string::String,
15};
16
17use crate::Itertools;
18use crate::intersperse::{Intersperse, IntersperseWith};
19
20pub use crate::adaptors::{
21 interleave,
22 merge,
23 put_back,
24};
25#[cfg(feature = "use_alloc")]
26pub use crate::put_back_n_impl::put_back_n;
27#[cfg(feature = "use_alloc")]
28pub use crate::multipeek_impl::multipeek;
29#[cfg(feature = "use_alloc")]
30pub use crate::peek_nth::peek_nth;
31#[cfg(feature = "use_alloc")]
32pub use crate::kmerge_impl::kmerge;
33pub use crate::zip_eq_impl::zip_eq;
34pub use crate::merge_join::merge_join_by;
35#[cfg(feature = "use_alloc")]
36pub use crate::rciter_impl::rciter;
37
38/// Iterate `iterable` with a particular value inserted between each element.
39///
40/// [`IntoIterator`] enabled version of [`Iterator::intersperse`].
41///
42/// ```
43/// use itertools::intersperse;
44///
45/// itertools::assert_equal(intersperse((0..3), 8), vec![0, 8, 1, 8, 2]);
46/// ```
47pub fn intersperse<I>(iterable: I, element: I::Item) -> Intersperse<I::IntoIter>
48 where I: IntoIterator,
49 <I as IntoIterator>::Item: Clone
50{
51 Itertools::intersperse(iterable.into_iter(), element)
52}
53
54/// Iterate `iterable` with a particular value created by a function inserted
55/// between each element.
56///
57/// [`IntoIterator`] enabled version of [`Iterator::intersperse_with`].
58///
59/// ```
60/// use itertools::intersperse_with;
61///
62/// let mut i = 10;
63/// itertools::assert_equal(intersperse_with((0..3), || { i -= 1; i }), vec![0, 9, 1, 8, 2]);
64/// assert_eq!(i, 8);
65/// ```
66pub fn intersperse_with<I, F>(iterable: I, element: F) -> IntersperseWith<I::IntoIter, F>
67 where I: IntoIterator,
68 F: FnMut() -> I::Item
69{
70 Itertools::intersperse_with(iterable.into_iter(), element)
71}
72
73/// Iterate `iterable` with a running index.
74///
75/// [`IntoIterator`] enabled version of [`Iterator::enumerate`].
76///
77/// ```
78/// use itertools::enumerate;
79///
80/// for (i, elt) in enumerate(&[1, 2, 3]) {
81/// /* loop body */
82/// }
83/// ```
84pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
85 where I: IntoIterator
86{
87 iterable.into_iter().enumerate()
88}
89
90/// Iterate `iterable` in reverse.
91///
92/// [`IntoIterator`] enabled version of [`Iterator::rev`].
93///
94/// ```
95/// use itertools::rev;
96///
97/// for elt in rev(&[1, 2, 3]) {
98/// /* loop body */
99/// }
100/// ```
101pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
102 where I: IntoIterator,
103 I::IntoIter: DoubleEndedIterator
104{
105 iterable.into_iter().rev()
106}
107
108/// Converts the arguments to iterators and zips them.
109///
110/// [`IntoIterator`] enabled version of [`Iterator::zip`].
111///
112/// ## Example
113///
114/// ```
115/// use itertools::zip;
116///
117/// let mut result: Vec<(i32, char)> = Vec::new();
118///
119/// for (a, b) in zip(&[1, 2, 3, 4, 5], &['a', 'b', 'c']) {
120/// result.push((*a, *b));
121/// }
122/// assert_eq!(result, vec![(1, 'a'),(2, 'b'),(3, 'c')]);
123/// ```
124#[deprecated(note="Use [std::iter::zip](https://doc.rust-lang.org/std/iter/fn.zip.html) instead", since="0.10.4")]
125pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
126 where I: IntoIterator,
127 J: IntoIterator
128{
129 i.into_iter().zip(j)
130}
131
132
133/// Takes two iterables and creates a new iterator over both in sequence.
134///
135/// [`IntoIterator`] enabled version of [`Iterator::chain`].
136///
137/// ## Example
138/// ```
139/// use itertools::chain;
140///
141/// let mut result:Vec<i32> = Vec::new();
142///
143/// for element in chain(&[1, 2, 3], &[4]) {
144/// result.push(*element);
145/// }
146/// assert_eq!(result, vec![1, 2, 3, 4]);
147/// ```
148pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
149 where I: IntoIterator,
150 J: IntoIterator<Item = I::Item>
151{
152 i.into_iter().chain(j)
153}
154
155/// Create an iterator that clones each element from &T to T
156///
157/// [`IntoIterator`] enabled version of [`Iterator::cloned`].
158///
159/// ```
160/// use itertools::cloned;
161///
162/// assert_eq!(cloned(b"abc").next(), Some(b'a'));
163/// ```
164pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter>
165 where I: IntoIterator<Item=&'a T>,
166 T: Clone,
167{
168 iterable.into_iter().cloned()
169}
170
171/// Perform a fold operation over the iterable.
172///
173/// [`IntoIterator`] enabled version of [`Iterator::fold`].
174///
175/// ```
176/// use itertools::fold;
177///
178/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.);
179/// ```
180pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B
181 where I: IntoIterator,
182 F: FnMut(B, I::Item) -> B
183{
184 iterable.into_iter().fold(init, f)
185}
186
187/// Test whether the predicate holds for all elements in the iterable.
188///
189/// [`IntoIterator`] enabled version of [`Iterator::all`].
190///
191/// ```
192/// use itertools::all;
193///
194/// assert!(all(&[1, 2, 3], |elt| *elt > 0));
195/// ```
196pub fn all<I, F>(iterable: I, f: F) -> bool
197 where I: IntoIterator,
198 F: FnMut(I::Item) -> bool
199{
200 iterable.into_iter().all(f)
201}
202
203/// Test whether the predicate holds for any elements in the iterable.
204///
205/// [`IntoIterator`] enabled version of [`Iterator::any`].
206///
207/// ```
208/// use itertools::any;
209///
210/// assert!(any(&[0, -1, 2], |elt| *elt > 0));
211/// ```
212pub fn any<I, F>(iterable: I, f: F) -> bool
213 where I: IntoIterator,
214 F: FnMut(I::Item) -> bool
215{
216 iterable.into_iter().any(f)
217}
218
219/// Return the maximum value of the iterable.
220///
221/// [`IntoIterator`] enabled version of [`Iterator::max`].
222///
223/// ```
224/// use itertools::max;
225///
226/// assert_eq!(max(0..10), Some(9));
227/// ```
228pub fn max<I>(iterable: I) -> Option<I::Item>
229 where I: IntoIterator,
230 I::Item: Ord
231{
232 iterable.into_iter().max()
233}
234
235/// Return the minimum value of the iterable.
236///
237/// [`IntoIterator`] enabled version of [`Iterator::min`].
238///
239/// ```
240/// use itertools::min;
241///
242/// assert_eq!(min(0..10), Some(0));
243/// ```
244pub fn min<I>(iterable: I) -> Option<I::Item>
245 where I: IntoIterator,
246 I::Item: Ord
247{
248 iterable.into_iter().min()
249}
250
251
252/// Combine all iterator elements into one String, separated by `sep`.
253///
254/// [`IntoIterator`] enabled version of [`Itertools::join`].
255///
256/// ```
257/// use itertools::join;
258///
259/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3");
260/// ```
261#[cfg(feature = "use_alloc")]
262pub fn join<I>(iterable: I, sep: &str) -> String
263 where I: IntoIterator,
264 I::Item: Display
265{
266 iterable.into_iter().join(sep)
267}
268
269/// Sort all iterator elements into a new iterator in ascending order.
270///
271/// [`IntoIterator`] enabled version of [`Itertools::sorted`].
272///
273/// ```
274/// use itertools::sorted;
275/// use itertools::assert_equal;
276///
277/// assert_equal(sorted("rust".chars()), "rstu".chars());
278/// ```
279#[cfg(feature = "use_alloc")]
280pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item>
281 where I: IntoIterator,
282 I::Item: Ord
283{
284 iterable.into_iter().sorted()
285}
286
287