Skip to content

Instantly share code, notes, and snippets.

@jyn514
Last active August 14, 2019 12:43
Show Gist options
  • Save jyn514/fa4b636c37554eaf83a10c94c0f8977d to your computer and use it in GitHub Desktop.
Save jyn514/fa4b636c37554eaf83a10c94c0f8977d to your computer and use it in GitHub Desktop.
try_max_by_key
/// short-circuiting version of iter.max_by_key
///
/// partially taken from https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#2591
///
/// Example:
///
/// ```
/// let list = [[1, 2, 3], [5, 4, 3], [1, 1, 4]];
/// assert_eq!(try_max_by_key(list.into_iter(), |vec| vec.last().ok_or(())), Some(Ok(&[1, 1, 4])));
///
/// let lengths = [vec![], vec![1], vec![1, 2]];
/// assert_eq!(try_max_by_key(lengths.into_iter(), |vec| vec.last().ok_or(())), Some(Err(())));
/// ```
pub fn try_max_by_key<I, T, C, R, F>(mut iter: I, mut f: F) -> Option<Result<T, R>>
where
I: Iterator<Item = T>,
C: std::cmp::Ord,
F: FnMut(&T) -> Result<C, R>,
{
iter.next().map(|initial| {
// if this gives an error, return it immediately
// avoids f not being called if there's only one element
f(&initial)?;
iter.try_fold(initial, |current, next| {
if f(&current)? >= f(&next)? {
Ok(current)
} else {
Ok(next)
}
})
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment