Skip to content

Commit

Permalink
Add Iterator::find_map
Browse files Browse the repository at this point in the history
  • Loading branch information
matklad committed Apr 2, 2018
1 parent 14ac1b5 commit 591dd5d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,38 @@ pub trait Iterator {
}).break_value()
}

/// Applies function to the elements of iterator and returns
/// the first non-none result.
///
/// `iter.find_map(f)` is equivalent to `iter.filter_map(f).next()`.
///
///
/// # Examples
///
/// ```
/// #![feature(iterator_find_map)]
/// let a = ["lol", "NaN", "2", "5"];
///
/// let mut first_number = a.iter().find_map(|s| s.parse().ok());
///
/// assert_eq!(first_number, Some(2));
/// ```
#[inline]
#[unstable(feature = "iterator_find_map",
reason = "unstable new API",
issue = "49602")]
fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
{
self.try_for_each(move |x| {
match f(x) {
Some(x) => LoopState::Break(x),
None => LoopState::Continue(()),
}
}).break_value()
}

/// Searches for an element in an iterator, returning its index.
///
/// `position()` takes a closure that returns `true` or `false`. It applies
Expand Down
27 changes: 27 additions & 0 deletions src/libcore/tests/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,33 @@ fn test_find() {
assert!(v.iter().find(|&&x| x % 12 == 0).is_none());
}

#[test]
fn test_find_map() {
let xs: &[isize] = &[];
assert_eq!(xs.iter().find_map(half_if_even), None);
let xs: &[isize] = &[3, 5];
assert_eq!(xs.iter().find_map(half_if_even), None);
let xs: &[isize] = &[4, 5];
assert_eq!(xs.iter().find_map(half_if_even), Some(2));
let xs: &[isize] = &[3, 6];
assert_eq!(xs.iter().find_map(half_if_even), Some(3));

let xs: &[isize] = &[1, 2, 3, 4, 5, 6, 7];
let mut iter = xs.iter();
assert_eq!(iter.find_map(half_if_even), Some(1));
assert_eq!(iter.find_map(half_if_even), Some(2));
assert_eq!(iter.find_map(half_if_even), Some(3));
assert_eq!(iter.next(), Some(&7));

fn half_if_even(x: &isize) -> Option<isize> {
if x % 2 == 0 {
Some(x / 2)
} else {
None
}
}
}

#[test]
fn test_position() {
let v = &[1, 3, 9, 27, 103, 14, 11];
Expand Down
1 change: 1 addition & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#![feature(atomic_nand)]
#![feature(reverse_bits)]
#![feature(inclusive_range_fields)]
#![feature(iterator_find_map)]

extern crate core;
extern crate test;
Expand Down

0 comments on commit 591dd5d

Please sign in to comment.