Skip to content

Commit db9e217

Browse files
authored
Rollup merge of #109409 - WaffleLapkin:progamer, r=dtolnay
Add `minmax{,_by,_by_key}` functions to `core::cmp` This PR adds the following functions: ```rust // mod core::cmp #![unstable(feature = "cmp_minmax")] pub fn minmax<T>(v1: T, v2: T) -> [T; 2] where T: Ord; pub fn minmax_by<T, F>(v1: T, v2: T, compare: F) -> [T; 2] where F: FnOnce(&T, &T) -> Ordering; pub fn minmax_by_key<T, F, K>(v1: T, v2: T, mut f: F) -> [T; 2] where F: FnMut(&T) -> K, K: Ord; ``` (they are also `const` under `#[feature(const_cmp)]`, I've omitted `const` stuff for simplicity/readability) ---- Semantically these functions are equivalent to `{ let mut arr = [v1, v2]; arr.sort(); arr }`, but since they operate on 2 elements only, they are implemented as a single comparison. Even though that's basically a sort, I think "sort 2 elements" operation is useful on it's own in many cases. Namely, it's a common pattern when you have 2 things, and need to know which one is smaller/bigger to operate on them differently. I've wanted such functions countless times, most recently in #109402, so I thought I'd propose them. ---- r? libs-api
2 parents cbcf9a5 + 0c3e0ab commit db9e217

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

library/core/src/cmp.rs

+85
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,91 @@ pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
12891289
max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
12901290
}
12911291

1292+
/// Compares and sorts two values, returning minimum and maximum.
1293+
///
1294+
/// Returns `[v1, v2]` if the comparison determines them to be equal.
1295+
///
1296+
/// # Examples
1297+
///
1298+
/// ```
1299+
/// #![feature(cmp_minmax)]
1300+
/// use std::cmp;
1301+
///
1302+
/// assert_eq!(cmp::minmax(1, 2), [1, 2]);
1303+
/// assert_eq!(cmp::minmax(2, 2), [2, 2]);
1304+
///
1305+
/// // You can destructure the result using array patterns
1306+
/// let [min, max] = cmp::minmax(42, 17);
1307+
/// assert_eq!(min, 17);
1308+
/// assert_eq!(max, 42);
1309+
/// ```
1310+
#[inline]
1311+
#[must_use]
1312+
#[unstable(feature = "cmp_minmax", issue = "115939")]
1313+
pub fn minmax<T>(v1: T, v2: T) -> [T; 2]
1314+
where
1315+
T: Ord,
1316+
{
1317+
if v1 <= v2 { [v1, v2] } else { [v2, v1] }
1318+
}
1319+
1320+
/// Returns minimum and maximum values with respect to the specified comparison function.
1321+
///
1322+
/// Returns `[v1, v2]` if the comparison determines them to be equal.
1323+
///
1324+
/// # Examples
1325+
///
1326+
/// ```
1327+
/// #![feature(cmp_minmax)]
1328+
/// use std::cmp;
1329+
///
1330+
/// assert_eq!(cmp::minmax_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [1, -2]);
1331+
/// assert_eq!(cmp::minmax_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [-2, 2]);
1332+
///
1333+
/// // You can destructure the result using array patterns
1334+
/// let [min, max] = cmp::minmax_by(-42, 17, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
1335+
/// assert_eq!(min, 17);
1336+
/// assert_eq!(max, -42);
1337+
/// ```
1338+
#[inline]
1339+
#[must_use]
1340+
#[unstable(feature = "cmp_minmax", issue = "115939")]
1341+
pub fn minmax_by<T, F>(v1: T, v2: T, compare: F) -> [T; 2]
1342+
where
1343+
F: FnOnce(&T, &T) -> Ordering,
1344+
{
1345+
if compare(&v1, &v2).is_le() { [v1, v2] } else { [v2, v1] }
1346+
}
1347+
1348+
/// Returns minimum and maximum values with respect to the specified key function.
1349+
///
1350+
/// Returns `[v1, v2]` if the comparison determines them to be equal.
1351+
///
1352+
/// # Examples
1353+
///
1354+
/// ```
1355+
/// #![feature(cmp_minmax)]
1356+
/// use std::cmp;
1357+
///
1358+
/// assert_eq!(cmp::minmax_by_key(-2, 1, |x: &i32| x.abs()), [1, -2]);
1359+
/// assert_eq!(cmp::minmax_by_key(-2, 2, |x: &i32| x.abs()), [-2, 2]);
1360+
///
1361+
/// // You can destructure the result using array patterns
1362+
/// let [min, max] = cmp::minmax_by_key(-42, 17, |x: &i32| x.abs());
1363+
/// assert_eq!(min, 17);
1364+
/// assert_eq!(max, -42);
1365+
/// ```
1366+
#[inline]
1367+
#[must_use]
1368+
#[unstable(feature = "cmp_minmax", issue = "115939")]
1369+
pub fn minmax_by_key<T, F, K>(v1: T, v2: T, mut f: F) -> [T; 2]
1370+
where
1371+
F: FnMut(&T) -> K,
1372+
K: Ord,
1373+
{
1374+
minmax_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
1375+
}
1376+
12921377
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
12931378
mod impls {
12941379
use crate::cmp::Ordering::{self, Equal, Greater, Less};

0 commit comments

Comments
 (0)