8000 Add `cmp::{min_by, min_by_key, max_by, max_by_key}` by timvermeulen · Pull Request #64047 · rust-lang/rust · GitHub
[go: up one dir, main page]

Skip to content

Add cmp::{min_by, min_by_key, max_by, max_by_key} #64047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 21, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add cmp::{min_by, min_by_key, max_by, max_by_key}
  • Loading branch information
timvermeulen committed Sep 14, 2019
commit 6e5ada43bf84b15a8dd4d55f5bee3ba1a9939bfe
90 changes: 88 additions & 2 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
#[inline]
fn max(self, other: Self) -> Self
where Self: Sized {
if other >= self { other } else { self }
max_by(self, other, Ord::cmp)
}

/// Compares and returns the minimum of two values.
Expand All @@ -587,7 +587,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
#[inline]
fn min(self, other: Self) -> Self
where Self: Sized {
if self <= other { self } else { other }
min_by(self, other, Ord::cmp)
}

/// Restrict a value to a certain interval.
Expand Down Expand Up @@ -898,6 +898,49 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
v1.min(v2)
}

/// Returns the minimum of two values with respect to the specified comparison function.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// #![feature(cmp_min_max_by)]
///
/// use std::cmp;
///
/// assert_eq!(cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 1);
/// assert_eq!(cmp::min_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2);
/// ```
#[inline]
#[unstable(feature = "cmp_min_max_by", issue = "64460")]
pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
Ordering::Greater => v2,
}
}

/// Returns the element that gives the minimum value from the specified function.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// #![feature(cmp_min_max_by)]
///
/// use std::cmp;
///
/// assert_eq!(cmp::min_by_key(-2, 1, |x: &i32| x.abs()), 1);
/// assert_eq!(cmp::min_by_key(-2, 2, |x: &i32| x.abs()), -2);
/// ```
#[inline]
#[unstable(feature = "cmp_min_max_by", issue = "64460")]
pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}

/// Compares and returns the maximum of two values.
///
/// Returns the second argument if the comparison determines them to be equal.
Expand All @@ -918,6 +961,49 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
v1.max(v2)
}

/// Returns the maximum of two values with respect to the specified comparison function.
///
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// #![feature(cmp_min_max_by)]
///
/// use std::cmp;
///
/// assert_eq!(cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2);
/// assert_eq!(cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 2);
/// ```
#[inline]
#[unstable(feature = "cmp_min_max_by", issue = "64460")]
pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
Ordering::Greater => v1,
}
}

/// Returns the element that gives the maximum value from the specified function.
///
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// #![feature(cmp_min_max_by)]
///
/// use std::cmp;
///
/// assert_eq!(cmp::max_by_key(-2, 1, |x: &i32| x.abs()), -2);
/// assert_eq!(cmp::max_by_key(-2, 2, |x: &i32| x.abs()), 2);
/// ```
#[inline]
#[unstable(feature = "cmp_min_max_by", issue = "64460")]
pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}

// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
mod impls {
use crate::cmp::Ordering::{self, Less, Greater, Equal};
Expand Down
24 changes: 23 additions & 1 deletion src/libcore/tests/cmp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::cmp::Ordering::{Less, Greater, Equal};
use core::cmp::{self, Ordering::*};

#[test]
fn test_int_totalord() {
Expand Down Expand Up @@ -28,6 +28,28 @@ fn test_ord_max_min() {
assert_eq!(1.min(1), 1);
}

#[test]
fn test_ord_min_max_by() {
let f = |x: &i32, y: &i32| x.abs().cmp(&y.abs());
assert_eq!(cmp::min_by(1, -1, f), 1);
assert_eq!(cmp::min_by(1, -2, f), 1);
assert_eq!(cmp::min_by(2, -1, f), -1);
assert_eq!(cmp::max_by(1, -1, f), -1);
assert_eq!(cmp::max_by(1, -2, f), -2);
assert_eq!(cmp::max_by(2, -1, f), 2);
}

#[test]
fn test_ord_min_max_by_key() {
let f = |x: &i32| x.abs();
assert_eq!(cmp::min_by_key(1, -1, f), 1);
assert_eq!(cmp::min_by_key(1, -2, f), 1);
assert_eq!(cmp::min_by_key(2, -1, f), -1);
assert_eq!(cmp::max_by_key(1, -1, f), -1);
assert_eq!(cmp::max_by_key(1, -2, f), -2);
assert_eq!(cmp::max_by_key(2, -1, f), 2);
}

#[test] 997A
fn test_ordering_reverse() {
assert_eq!(Less.reverse(), Greater);
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 @@ -34,6 +34,7 @@
#![feature(iter_partition_in_place)]
#![feature(iter_is_partitioned)]
#![feature(iter_order_by)]
#![feature(cmp_min_max_by)]

extern crate test;

Expand Down
0