Skip to content

Commit

Permalink
Introduce max_by/min_by on iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
philipp committed Aug 20, 2016
1 parent 7ac11ca commit 4b87c7e
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,31 @@ pub trait Iterator {
.map(|(_, x)| x)
}

/// Returns the element that gives the maximum value with respect to the
/// specified comparison function.
///
/// Returns the rightmost element if the comparison determines two elements
/// to be equally maximum.
///
/// # Examples
///
/// ```
/// let a = [-3_i32, 0, 1, 5, -10];
/// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5);
/// ```
#[inline]
#[unstable(feature = "iter_max_by", issue="1722")]
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
select_fold1(self,
|_| (),
// switch to y even if it is only equal, to preserve
// stability.
|_, x, _, y| Ordering::Greater != compare(x, y))
.map(|(_, x)| x)
}

/// Returns the element that gives the minimum value from the
/// specified function.
///
Expand All @@ -1688,6 +1713,32 @@ pub trait Iterator {
.map(|(_, x)| x)
}

/// Returns the element that gives the minimum value with respect to the
/// specified comparison function.
///
/// Returns the latest element if the comparison determines two elements
/// to be equally minimum.
///
/// # Examples
///
/// ```
/// let a = [-3_i32, 0, 1, 5, -10];
/// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10);
/// ```
#[inline]
#[unstable(feature = "iter_min_by", issue="1722")]
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
select_fold1(self,
|_| (),
// switch to y even if it is strictly smaller, to
// preserve stability.
|_, x, _, y| Ordering::Greater == compare(x, y))
.map(|(_, x)| x)
}


/// Reverses an iterator's direction.
///
/// Usually, iterators iterate from left to right. After using `rev()`,
Expand Down
12 changes: 12 additions & 0 deletions src/libcoretest/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,12 +664,24 @@ fn test_max_by_key() {
assert_eq!(*xs.iter().max_by_key(|x| x.abs()).unwrap(), -10);
}

#[test]
fn test_max_by() {
let xs: &[isize] = &[-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().max_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), -10);
}

#[test]
fn test_min_by_key() {
let xs: &[isize] = &[-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().min_by_key(|x| x.abs()).unwrap(), 0);
}

#[test]
fn test_min_by() {
let xs: &[isize] = &[-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().min_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), 0);
}

#[test]
fn test_by_ref() {
let mut xs = 0..10;
Expand Down
2 changes: 2 additions & 0 deletions src/libcoretest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#![feature(try_from)]
#![feature(unicode)]
#![feature(unique)]
#![feature(iter_max_by)]
#![feature(iter_min_by)]

extern crate core;
extern crate test;
Expand Down

0 comments on commit 4b87c7e

Please sign in to comment.