pub(crate) struct BestBy<T, K> {
best: Option<(T, K)>,
}
impl<T, K: PartialOrd> BestBy<T, K> {
pub(crate) fn new() -> Self {
BestBy { best: None }
}
pub(crate) fn offer(&mut self, item: T, key: K) {
if self.best.as_ref().is_none_or(|(_, bk)| key < *bk) {
self.best = Some((item, key));
}
}
pub(crate) fn has_candidate(&self) -> bool {
self.best.is_some()
}
pub(crate) fn into_best(self) -> Option<(T, K)> {
self.best
}
}
pub(crate) fn select_first_min<T, K: PartialOrd>(
items: impl IntoIterator<Item = T>,
key: impl Fn(&T) -> K,
) -> Option<T> {
let mut best = BestBy::new();
for item in items {
let k = key(&item);
best.offer(item, k);
}
best.into_best().map(|(item, _)| item)
}