Skip to content

Commit 8a5057a

Browse files
committed
std::iter: Add partition and unzip methods to iterators
1 parent 84f5ad8 commit 8a5057a

File tree

3 files changed

+78
-17
lines changed

3 files changed

+78
-17
lines changed

src/libcore/iter.rs

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub use self::MinMaxResult::*;
5959
use clone::Clone;
6060
use cmp;
6161
use cmp::Ord;
62+
use default::Default;
6263
use mem;
6364
use num::{ToPrimitive, Int};
6465
use ops::{Add, Deref, FnMut};
@@ -68,20 +69,6 @@ use uint;
6869

6970
#[deprecated = "renamed to Extend"] pub use self::Extend as Extendable;
7071

71-
/// Conversion from an `Iterator`
72-
#[unstable = "may be replaced by a more general conversion trait"]
73-
pub trait FromIterator<A> {
74-
/// Build a container with elements from an external iterator.
75-
fn from_iter<T: Iterator<A>>(iterator: T) -> Self;
76-
}
77-
78-
/// A type growable from an `Iterator` implementation
79-
#[unstable = "just renamed as part of collections reform"]
80-
pub trait Extend<A> {
81-
/// Extend a container with the elements yielded by an arbitrary iterator
82-
fn extend<T: Iterator<A>>(&mut self, iterator: T);
83-
}
84-
8572
/// An interface for dealing with "external iterators". These types of iterators
8673
/// can be resumed at any time as all state is stored internally as opposed to
8774
/// being located on the call stack.
@@ -106,6 +93,20 @@ pub trait Iterator<A> {
10693
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
10794
}
10895

96+
/// Conversion from an `Iterator`
97+
#[unstable = "may be replaced by a more general conversion trait"]
98+
pub trait FromIterator<A> {
99+
/// Build a container with elements from an external iterator.
100+
fn from_iter<T: Iterator<A>>(iterator: T) -> Self;
101+
}
102+
103+
/// A type growable from an `Iterator` implementation
104+
#[unstable = "just renamed as part of collections reform"]
105+
pub trait Extend<A> {
106+
/// Extend a container with the elements yielded by an arbitrary iterator
107+
fn extend<T: Iterator<A>>(&mut self, iterator: T);
108+
}
109+
109110
#[unstable = "new convention for extension traits"]
110111
/// An extension trait providing numerous methods applicable to all iterators.
111112
pub trait IteratorExt<A>: Iterator<A> {
@@ -223,7 +224,6 @@ pub trait IteratorExt<A>: Iterator<A> {
223224
Enumerate{iter: self, count: 0}
224225
}
225226

226-
227227
/// Creates an iterator that has a `.peek()` method
228228
/// that returns an optional reference to the next element.
229229
///
@@ -471,6 +471,35 @@ pub trait IteratorExt<A>: Iterator<A> {
471471
FromIterator::from_iter(self)
472472
}
473473

474+
/// Loops through the entire iterator, collecting all of the elements into
475+
/// one of two containers, depending on a predicate. The elements of the
476+
/// first container satisfy the predicate, while the elements of the second
477+
/// do not.
478+
///
479+
/// ```
480+
/// let vec = vec![1i, 2i, 3i, 4i];
481+
/// let (even, odd): (Vec<int>, Vec<Int>) = vec.into_iter().partition(|&n| n % 2 == 0);
482+
/// assert_eq!(even, vec![2, 4]);
483+
/// assert_eq!(odd, vec![1, 3]);
484+
/// ```
485+
#[unstable = "recently added as part of collections reform"]
486+
fn partition<B, F>(mut self, mut f: F) -> (B, B) where
487+
B: Default + Extend<A>, F: FnMut(&A) -> bool
488+
{
489+
let mut left: B = Default::default();
490+
let mut right: B = Default::default();
491+
492+
for x in self {
493+
if f(&x) {
494+
left.extend(Some(x).into_iter())
495+
} else {
496+
right.extend(Some(x).into_iter())
497+
}
498+
}
499+
500+
(left, right)
501+
}
502+
474503
/// Loops through `n` iterations, returning the `n`th element of the
475504
/// iterator.
476505
///
@@ -661,6 +690,38 @@ pub trait IteratorExt<A>: Iterator<A> {
661690
#[unstable = "trait is unstable"]
662691
impl<A, I> IteratorExt<A> for I where I: Iterator<A> {}
663692

693+
/// Extention trait for iterators of pairs.
694+
pub trait IteratorPairExt<A, B>: Iterator<(A, B)> {
695+
/// Converts an iterator of pairs into a pair of containers.
696+
///
697+
/// Loops through the entire iterator, collecting the first component of
698+
/// each item into one new container, and the second component into another.
699+
fn unzip<FromA, FromB>(mut self) -> (FromA, FromB) where
700+
FromA: FromIterator<A> + Extend<A>, FromB: FromIterator<B> + Extend<B>
701+
{
702+
struct SizeHint<A>(uint, Option<uint>);
703+
impl<A> Iterator<A> for SizeHint<A> {
704+
fn next(&mut self) -> Option<A> { None }
705+
fn size_hint(&self) -> (uint, Option<uint>) {
706+
(self.0, self.1)
707+
}
708+
}
709+
710+
let (lo, hi) = self.size_hint();
711+
let mut ts: FromA = FromIterator::from_iter(SizeHint(lo, hi));
712+
let mut us: FromB = FromIterator::from_iter(SizeHint(lo, hi));
713+
714+
for (t, u) in self {
715+
ts.extend(Some(t).into_iter());
716+
us.extend(Some(u).into_iter());
717+
}
718+
719+
(ts, us)
720+
}
721+
}
722+
723+
impl<A, B, I> IteratorPairExt<A, B> for I where I: Iterator<(A, B)> {}
724+
664725
/// A range iterator able to yield elements from both ends
665726
///
666727
/// A `DoubleEndedIterator` can be thought of as a deque in that `next()` and `next_back()` exhaust

src/libcore/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub use cmp::{Ordering, Equiv};
5252
pub use cmp::Ordering::{Less, Equal, Greater};
5353
pub use iter::{FromIterator, Extend, IteratorExt};
5454
pub use iter::{Iterator, DoubleEndedIterator, DoubleEndedIteratorExt, RandomAccessIterator};
55-
pub use iter::{IteratorCloneExt, CloneIteratorExt};
55+
pub use iter::{IteratorCloneExt, CloneIteratorExt, IteratorPairExt};
5656
pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator, ExactSizeIterator};
5757
pub use num::{ToPrimitive, FromPrimitive};
5858
pub use option::Option;

src/libstd/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
#[doc(no_inline)] pub use iter::{FromIterator, Extend, ExactSizeIterator};
6767
#[doc(no_inline)] pub use iter::{Iterator, IteratorExt, DoubleEndedIterator};
6868
#[doc(no_inline)] pub use iter::{DoubleEndedIteratorExt, CloneIteratorExt};
69-
#[doc(no_inline)] pub use iter::{RandomAccessIterator, IteratorCloneExt};
69+
#[doc(no_inline)] pub use iter::{RandomAccessIterator, IteratorCloneExt, IteratorPairExt};
7070
#[doc(no_inline)] pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator};
7171
#[doc(no_inline)] pub use num::{ToPrimitive, FromPrimitive};
7272
#[doc(no_inline)] pub use boxed::Box;

0 commit comments

Comments
 (0)