Skip to content

Commit d128e6b

Browse files
authored
Auto merge of #35856 - phimuemue:master, r=brson
Introduce max_by/min_by on iterators See rust-lang/rfcs#1722 for reference. It seems that there is `min`, `max` (simple computation of min/max), `min_by_key`, `max_by_key` (min/max by comparing mapped values) but no `min_by` and `max_by` (min/max according to comparison function). However, e.g. on vectors or slices there is `sort`, `sort_by_key` and `sort_by`.
2 parents 100b309 + 5928be1 commit d128e6b

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

src/libcore/iter/iterator.rs

+53
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,32 @@ pub trait Iterator {
16571657
.map(|(_, x)| x)
16581658
}
16591659

1660+
/// Returns the element that gives the maximum value with respect to the
1661+
/// specified comparison function.
1662+
///
1663+
/// Returns the rightmost element if the comparison determines two elements
1664+
/// to be equally maximum.
1665+
///
1666+
/// # Examples
1667+
///
1668+
/// ```
1669+
/// #![feature(iter_max_by)]
1670+
/// let a = [-3_i32, 0, 1, 5, -10];
1671+
/// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5);
1672+
/// ```
1673+
#[inline]
1674+
#[unstable(feature = "iter_max_by", issue="36105")]
1675+
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
1676+
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
1677+
{
1678+
select_fold1(self,
1679+
|_| (),
1680+
// switch to y even if it is only equal, to preserve
1681+
// stability.
1682+
|_, x, _, y| Ordering::Greater != compare(x, y))
1683+
.map(|(_, x)| x)
1684+
}
1685+
16601686
/// Returns the element that gives the minimum value from the
16611687
/// specified function.
16621688
///
@@ -1681,6 +1707,33 @@ pub trait Iterator {
16811707
.map(|(_, x)| x)
16821708
}
16831709

1710+
/// Returns the element that gives the minimum value with respect to the
1711+
/// specified comparison function.
1712+
///
1713+
/// Returns the latest element if the comparison determines two elements
1714+
/// to be equally minimum.
1715+
///
1716+
/// # Examples
1717+
///
1718+
/// ```
1719+
/// #![feature(iter_min_by)]
1720+
/// let a = [-3_i32, 0, 1, 5, -10];
1721+
/// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10);
1722+
/// ```
1723+
#[inline]
1724+
#[unstable(feature = "iter_min_by", issue="36105")]
1725+
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
1726+
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
1727+
{
1728+
select_fold1(self,
1729+
|_| (),
1730+
// switch to y even if it is strictly smaller, to
1731+
// preserve stability.
1732+
|_, x, _, y| Ordering::Greater == compare(x, y))
1733+
.map(|(_, x)| x)
1734+
}
1735+
1736+
16841737
/// Reverses an iterator's direction.
16851738
///
16861739
/// 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
@@ -32,6 +32,8 @@
3232
#![feature(try_from)]
3333
#![feature(unicode)]
3434
#![feature(unique)]
35+
#![feature(iter_max_by)]
36+
#![feature(iter_min_by)]
3537

3638
extern crate core;
3739
extern crate test;

0 commit comments

Comments
 (0)