blob: bfc5ab42207bc538e9e053a989928f1b57f84236 [file] [log] [blame]
Jakub Kotura425e552020-12-21 17:28:15 +01001//! 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
Joel Galenson6f798712021-04-01 17:03:06 -07006#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +01007use std::fmt::Display;
8use std::iter::{self, Zip};
Joel Galenson6f798712021-04-01 17:03:06 -07009#[cfg(feature = "use_alloc")]
10type VecIntoIter<T> = alloc::vec::IntoIter<T>;
Jakub Kotura425e552020-12-21 17:28:15 +010011
Joel Galenson6f798712021-04-01 17:03:06 -070012#[cfg(feature = "use_alloc")]
13use alloc::{
14 string::String,
15};
16
17#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +010018use crate::Itertools;
19
20pub use crate::adaptors::{
21 interleave,
22 merge,
23 put_back,
24};
Joel Galenson6f798712021-04-01 17:03:06 -070025#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +010026pub use crate::put_back_n_impl::put_back_n;
Joel Galenson6f798712021-04-01 17:03:06 -070027#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +010028pub use crate::multipeek_impl::multipeek;
Joel Galenson6f798712021-04-01 17:03:06 -070029#[cfg(feature = "use_alloc")]
30pub use crate::peek_nth::peek_nth;
31#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +010032pub use crate::kmerge_impl::kmerge;
33pub use crate::zip_eq_impl::zip_eq;
34pub use crate::merge_join::merge_join_by;
Joel Galenson6f798712021-04-01 17:03:06 -070035#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +010036pub use crate::rciter_impl::rciter;
37
38/// Iterate `iterable` with a running index.
39///
40/// `IntoIterator` enabled version of `.enumerate()`.
41///
42/// ```
43/// use itertools::enumerate;
44///
45/// for (i, elt) in enumerate(&[1, 2, 3]) {
46/// /* loop body */
47/// }
48/// ```
49pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
50 where I: IntoIterator
51{
52 iterable.into_iter().enumerate()
53}
54
55/// Iterate `iterable` in reverse.
56///
57/// `IntoIterator` enabled version of `.rev()`.
58///
59/// ```
60/// use itertools::rev;
61///
62/// for elt in rev(&[1, 2, 3]) {
63/// /* loop body */
64/// }
65/// ```
66pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
67 where I: IntoIterator,
68 I::IntoIter: DoubleEndedIterator
69{
70 iterable.into_iter().rev()
71}
72
73/// Iterate `i` and `j` in lock step.
74///
75/// `IntoIterator` enabled version of `i.zip(j)`.
76///
77/// ```
78/// use itertools::zip;
79///
80/// let data = [1, 2, 3, 4, 5];
81/// for (a, b) in zip(&data, &data[1..]) {
82/// /* loop body */
83/// }
84/// ```
85pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
86 where I: IntoIterator,
87 J: IntoIterator
88{
89 i.into_iter().zip(j)
90}
91
92/// Create an iterator that first iterates `i` and then `j`.
93///
94/// `IntoIterator` enabled version of `i.chain(j)`.
95///
96/// ```
97/// use itertools::chain;
98///
99/// for elt in chain(&[1, 2, 3], &[4]) {
100/// /* loop body */
101/// }
102/// ```
103pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
104 where I: IntoIterator,
105 J: IntoIterator<Item = I::Item>
106{
107 i.into_iter().chain(j)
108}
109
110/// Create an iterator that clones each element from &T to T
111///
112/// `IntoIterator` enabled version of `i.cloned()`.
113///
114/// ```
115/// use itertools::cloned;
116///
117/// assert_eq!(cloned(b"abc").next(), Some(b'a'));
118/// ```
119pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter>
120 where I: IntoIterator<Item=&'a T>,
121 T: Clone,
122{
123 iterable.into_iter().cloned()
124}
125
126/// Perform a fold operation over the iterable.
127///
128/// `IntoIterator` enabled version of `i.fold(init, f)`
129///
130/// ```
131/// use itertools::fold;
132///
133/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.);
134/// ```
135pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B
136 where I: IntoIterator,
137 F: FnMut(B, I::Item) -> B
138{
139 iterable.into_iter().fold(init, f)
140}
141
142/// Test whether the predicate holds for all elements in the iterable.
143///
144/// `IntoIterator` enabled version of `i.all(f)`
145///
146/// ```
147/// use itertools::all;
148///
149/// assert!(all(&[1, 2, 3], |elt| *elt > 0));
150/// ```
151pub fn all<I, F>(iterable: I, f: F) -> bool
152 where I: IntoIterator,
153 F: FnMut(I::Item) -> bool
154{
155 iterable.into_iter().all(f)
156}
157
158/// Test whether the predicate holds for any elements in the iterable.
159///
160/// `IntoIterator` enabled version of `i.any(f)`
161///
162/// ```
163/// use itertools::any;
164///
165/// assert!(any(&[0, -1, 2], |elt| *elt > 0));
166/// ```
167pub fn any<I, F>(iterable: I, f: F) -> bool
168 where I: IntoIterator,
169 F: FnMut(I::Item) -> bool
170{
171 iterable.into_iter().any(f)
172}
173
174/// Return the maximum value of the iterable.
175///
176/// `IntoIterator` enabled version of `i.max()`.
177///
178/// ```
179/// use itertools::max;
180///
181/// assert_eq!(max(0..10), Some(9));
182/// ```
183pub fn max<I>(iterable: I) -> Option<I::Item>
184 where I: IntoIterator,
185 I::Item: Ord
186{
187 iterable.into_iter().max()
188}
189
190/// Return the minimum value of the iterable.
191///
192/// `IntoIterator` enabled version of `i.min()`.
193///
194/// ```
195/// use itertools::min;
196///
197/// assert_eq!(min(0..10), Some(0));
198/// ```
199pub fn min<I>(iterable: I) -> Option<I::Item>
200 where I: IntoIterator,
201 I::Item: Ord
202{
203 iterable.into_iter().min()
204}
205
206
207/// Combine all iterator elements into one String, seperated by `sep`.
208///
209/// `IntoIterator` enabled version of `iterable.join(sep)`.
210///
211/// ```
212/// use itertools::join;
213///
214/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3");
215/// ```
Joel Galenson6f798712021-04-01 17:03:06 -0700216#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +0100217pub fn join<I>(iterable: I, sep: &str) -> String
218 where I: IntoIterator,
219 I::Item: Display
220{
221 iterable.into_iter().join(sep)
222}
223
224/// Sort all iterator elements into a new iterator in ascending order.
225///
226/// `IntoIterator` enabled version of [`iterable.sorted()`][1].
227///
228/// [1]: trait.Itertools.html#method.sorted
229///
230/// ```
231/// use itertools::sorted;
232/// use itertools::assert_equal;
233///
234/// assert_equal(sorted("rust".chars()), "rstu".chars());
235/// ```
Joel Galenson6f798712021-04-01 17:03:06 -0700236#[cfg(feature = "use_alloc")]
Jakub Kotura425e552020-12-21 17:28:15 +0100237pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item>
238 where I: IntoIterator,
239 I::Item: Ord
240{
241 iterable.into_iter().sorted()
242}
243