Skip to content

Add flatten() free function and fix flatten tests #266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions src/adaptors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,10 +1045,31 @@ pub struct Flatten<I, J> {
front: Option<J>,
}

/// Create a new `Flatten` iterator.
pub fn flatten<I, J>(iter: I) -> Flatten<I, J> {
/// 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<I, J>(iter: I) -> Flatten<I::IntoIter, J>
where I: IntoIterator,
I::Item: IntoIterator<IntoIter=J, Item=J::Item>,
J: Iterator,
{
Flatten {
iter: iter,
iter: iter.into_iter(),
front: None,
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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]];
Expand Down
5 changes: 3 additions & 2 deletions tests/quick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use itertools::{
multizip,
EitherOrBoth,
};
use itertools::flatten;
use itertools::free::{
cloned,
enumerate,
Expand Down Expand Up @@ -604,12 +605,12 @@ quickcheck! {
}

fn equal_flatten(a: Vec<Option<i32>>) -> bool {
itertools::equal(a.iter().flatten(),
itertools::equal(flatten(&a),
a.iter().filter_map(|x| x.as_ref()))
}

fn equal_flatten_vec(a: Vec<Vec<u8>>) -> bool {
itertools::equal(a.iter().flatten(),
itertools::equal(flatten(&a),
a.iter().flat_map(|x| x))
}

Expand Down
3 changes: 2 additions & 1 deletion tests/test_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#[macro_use] extern crate itertools as it;

use it::flatten;
use it::Itertools;
use it::interleave;
use it::multizip;
Expand Down Expand Up @@ -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]);
Expand Down
9 changes: 4 additions & 5 deletions tests/test_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down