diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index c51ac1cc3..08970d6b9 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -1045,10 +1045,31 @@ pub struct Flatten { front: Option, } -/// Create a new `Flatten` iterator. -pub fn flatten(iter: I) -> Flatten { +/// Flatten an iteratble of iterables into a single iteration of all +/// elements in the iterables. +/// +/// This is more or less equivalent to `.flat_map` with an identity +/// function. +/// +/// This is an `IntoIterator`-enabled version of the [`.flatten()`][1] adaptor. +/// +/// [1]: trait.Itertools.html#method.flatten. +/// +/// ``` +/// use itertools::flatten; +/// +/// let data = vec![vec![1, 2, 3], vec![4, 5, 6]]; +/// +/// itertools::assert_equal(flatten(&data), +/// &[1, 2, 3, 4, 5, 6]); +/// ``` +pub fn flatten(iter: I) -> Flatten + where I: IntoIterator, + I::Item: IntoIterator, + J: Iterator, +{ Flatten { - iter: iter, + iter: iter.into_iter(), front: None, } } diff --git a/src/lib.rs b/src/lib.rs index 247e6fe81..76412e7e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,7 @@ pub mod structs { pub use ziptuple::Zip; } pub use structs::*; +pub use adaptors::flatten; pub use concat_impl::concat; pub use cons_tuples_impl::cons_tuples; pub use diff::diff_with; @@ -1088,12 +1089,15 @@ pub trait Itertools : Iterator { pad_tail::pad_using(self, min, f) } - /// Unravel a nested iterator. + /// Flatten an iterator of iterables into a single iteration of all + /// elements in the iterables. /// /// This is more or less equivalent to `.flat_map` with an identity /// function. /// - /// ``` + /// See also the [`flatten`](fn.flatten.html) function. + /// + /// ```ignore /// use itertools::Itertools; /// /// let data = vec![vec![1, 2, 3], vec![4, 5, 6]]; diff --git a/tests/quick.rs b/tests/quick.rs index 6295a1d4f..cb859312a 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -17,6 +17,7 @@ use itertools::{ multizip, EitherOrBoth, }; +use itertools::flatten; use itertools::free::{ cloned, enumerate, @@ -604,12 +605,12 @@ quickcheck! { } fn equal_flatten(a: Vec>) -> bool { - itertools::equal(a.iter().flatten(), + itertools::equal(flatten(&a), a.iter().filter_map(|x| x.as_ref())) } fn equal_flatten_vec(a: Vec>) -> bool { - itertools::equal(a.iter().flatten(), + itertools::equal(flatten(&a), a.iter().flat_map(|x| x)) } diff --git a/tests/test_core.rs b/tests/test_core.rs index f0df210fa..7fc931c5a 100644 --- a/tests/test_core.rs +++ b/tests/test_core.rs @@ -7,6 +7,7 @@ #[macro_use] extern crate itertools as it; +use it::flatten; use it::Itertools; use it::interleave; use it::multizip; @@ -224,7 +225,7 @@ fn flatten_clone() { &[1,2,3], &[4,5,6] ]; - let flattened1 = data.into_iter().cloned().flatten(); + let flattened1 = flatten(data.into_iter().cloned()); let flattened2 = flattened1.clone(); it::assert_equal(flattened1, &[1,2,3,4,5,6]); diff --git a/tests/test_std.rs b/tests/test_std.rs index 1f7a46555..0341c61d6 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -2,6 +2,7 @@ #[macro_use] extern crate itertools as it; extern crate permutohedron; +use it::flatten; use it::Itertools; use it::multizip; use it::multipeek; @@ -539,17 +540,15 @@ fn concat_non_empty() { #[test] fn flatten_iter() { - let data = vec![vec![1,2,3], vec![4,5,6]]; - let flattened = data.into_iter().flatten(); - - it::assert_equal(flattened, vec![1,2,3,4,5,6]); + let data = vec![vec![1,2,3], vec![4,5], vec![], vec![6]]; + it::assert_equal(flatten(data), vec![1,2,3,4,5,6]); } #[test] fn flatten_fold() { let xs = [0, 1, 1, 1, 2, 1, 3, 3]; let ch = xs.iter().chunks(3); - let mut iter = ch.into_iter().flatten(); + let mut iter = flatten(&ch); iter.next(); let mut xs_d = Vec::new(); iter.fold((), |(), &elt| xs_d.push(elt));