Skip to content

Commit 4b87c7e

Browse files
author
philipp
committed
Introduce max_by/min_by on iterators
1 parent 7ac11ca commit 4b87c7e

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

src/libcore/iter/iterator.rs

+51
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,31 @@ pub trait Iterator {
16641664
.map(|(_, x)| x)
16651665
}
16661666

1667+
/// Returns the element that gives the maximum value with respect to the
1668+
/// specified comparison function.
1669+
///
1670+
/// Returns the rightmost element if the comparison determines two elements
1671+
/// to be equally maximum.
1672+
///
1673+
/// # Examples
1674+
///
1675+
/// ```
1676+
/// let a = [-3_i32, 0, 1, 5, -10];
1677+
/// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5);
1678+
/// ```
1679+
#[inline]
1680+
#[unstable(feature = "iter_max_by", issue="1722")]
1681+
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
1682+
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
1683+
{
1684+
select_fold1(self,
1685+
|_| (),
1686+
// switch to y even if it is only equal, to preserve
1687+
// stability.
1688+
|_, x, _, y| Ordering::Greater != compare(x, y))
1689+
.map(|(_, x)| x)
1690+
}
1691+
16671692
/// Returns the element that gives the minimum value from the
16681693
/// specified function.
16691694
///
@@ -1688,6 +1713,32 @@ pub trait Iterator {
16881713
.map(|(_, x)| x)
16891714
}
16901715

1716+
/// Returns the element that gives the minimum value with respect to the
1717+
/// specified comparison function.
1718+
///
1719+
/// Returns the latest element if the comparison determines two elements
1720+
/// to be equally minimum.
1721+
///
1722+
/// # Examples
1723+
///
1724+
/// ```
1725+
/// let a = [-3_i32, 0, 1, 5, -10];
1726+
/// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10);
1727+
/// ```
1728+
#[inline]
1729+
#[unstable(feature = "iter_min_by", issue="1722")]
1730+
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
1731+
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
1732+
{
1733+
select_fold1(self,
1734+
|_| (),
1735+
// switch to y even if it is strictly smaller, to
1736+
// preserve stability.
1737+
|_, x, _, y| Ordering::Greater == compare(x, y))
1738+
.map(|(_, x)| x)
1739+
}
1740+
1741+
16911742
/// Reverses an iterator's direction.
16921743
///
16931744
/// Usually, iterators iterate from left to right. After using `rev()`,

src/libcoretest/iter.rs

+12
Original file line numberDiff line numberDiff line change
@@ -664,12 +664,24 @@ fn test_max_by_key() {
664664
assert_eq!(*xs.iter().max_by_key(|x| x.abs()).unwrap(), -10);
665665
}
666666

667+
#[test]
668+
fn test_max_by() {
669+
let xs: &[isize] = &[-3, 0, 1, 5, -10];
670+
assert_eq!(*xs.iter().max_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), -10);
671+
}
672+
667673
#[test]
668674
fn test_min_by_key() {
669675
let xs: &[isize] = &[-3, 0, 1, 5, -10];
670676
assert_eq!(*xs.iter().min_by_key(|x| x.abs()).unwrap(), 0);
671677
}
672678

679+
#[test]
680+
fn test_min_by() {
681+
let xs: &[isize] = &[-3, 0, 1, 5, -10];
682+
assert_eq!(*xs.iter().min_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), 0);
683+
}
684+
673685
#[test]
674686
fn test_by_ref() {
675687
let mut xs = 0..10;

src/libcoretest/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#![feature(try_from)]
3434
#![feature(unicode)]
3535
#![feature(unique)]
36+
#![feature(iter_max_by)]
37+
#![feature(iter_min_by)]
3638

3739
extern crate core;
3840
extern crate test;

0 commit comments

Comments
 (0)