Skip to content

Commit 9ffbe69

Browse files
committed
libcore: Add IteratorUtil::filter_map method
1 parent f7e58eb commit 9ffbe69

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

src/libcore/iterator.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub trait IteratorUtil<A> {
3434
// FIXME: #5898: should be called map
3535
fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>;
3636
fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>;
37+
fn filter_map<'r, B>(self, f: &'r fn(A) -> Option<B>) -> FilterMapIterator<'r, A, B, Self>;
3738
fn enumerate(self) -> EnumerateIterator<Self>;
3839
fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>;
3940
fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>;
@@ -74,6 +75,11 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
7475
FilterIterator{iter: self, predicate: predicate}
7576
}
7677

78+
#[inline(always)]
79+
fn filter_map<'r, B>(self, f: &'r fn(A) -> Option<B>) -> FilterMapIterator<'r, A, B, T> {
80+
FilterMapIterator { iter: self, f: f }
81+
}
82+
7783
#[inline(always)]
7884
fn enumerate(self) -> EnumerateIterator<T> {
7985
EnumerateIterator{iter: self, count: 0}
@@ -213,6 +219,28 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
213219
}
214220
}
215221

222+
pub struct FilterMapIterator<'self, A, B, T> {
223+
priv iter: T,
224+
priv f: &'self fn(A) -> Option<B>
225+
}
226+
227+
impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B, T> {
228+
#[inline]
229+
fn next(&mut self) -> Option<B> {
230+
loop {
231+
match self.iter.next() {
232+
None => { return None; }
233+
Some(a) => {
234+
match (self.f)(a) {
235+
Some(b) => { return Some(b); }
236+
None => { loop; }
237+
}
238+
}
239+
}
240+
}
241+
}
242+
}
243+
216244
pub struct EnumerateIterator<T> {
217245
priv iter: T,
218246
priv count: uint
@@ -432,6 +460,13 @@ mod tests {
432460
assert_eq!(i, expected.len());
433461
}
434462

463+
#[test]
464+
fn test_filter_map() {
465+
let it = Counter::new(0u, 1u).take(10)
466+
.filter_map(|x: uint| if x.is_even() { Some(x*x) } else { None });
467+
assert_eq!(it.to_vec(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
468+
}
469+
435470
#[test]
436471
fn test_iterator_enumerate() {
437472
let xs = [0u, 1, 2, 3, 4, 5];

0 commit comments

Comments
 (0)