2
0
Fork 1
mirror of https://github.com/async-rs/async-std.git synced 2025-02-28 15:19:41 +00:00

add stream::min_by_key method

This commit is contained in:
yjhmelody 2019-10-23 18:59:06 +08:00
parent ec23632f3e
commit 020eb85093
2 changed files with 96 additions and 0 deletions

View file

@ -0,0 +1,58 @@
use std::cmp::Ordering;
use std::pin::Pin;
use crate::future::Future;
use crate::stream::Stream;
use crate::task::{Context, Poll};
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct MinByKeyFuture<S, T, K> {
stream: S,
min: Option<T>,
key_by: K,
}
impl<S, T, K> MinByKeyFuture<S, T, K> {
pin_utils::unsafe_pinned!(stream: S);
pin_utils::unsafe_unpinned!(min: Option<T>);
pin_utils::unsafe_unpinned!(key_by: K);
pub(super) fn new(stream: S, key_by: K) -> Self {
MinByKeyFuture {
stream,
min: None,
key_by,
}
}
}
impl<S, K> Future for MinByKeyFuture<S, S::Item, K>
where
S: Stream + Unpin + Sized,
K: FnMut(&S::Item) -> S::Item,
S::Item: Ord + Copy,
{
type Output = Option<S::Item>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let next = futures_core::ready!(self.as_mut().stream().poll_next(cx));
match next {
Some(new) => {
let new = self.as_mut().key_by()(&new);
cx.waker().wake_by_ref();
match self.as_mut().min().take() {
None => *self.as_mut().min() = Some(new),
Some(old) => match new.cmp(&old) {
Ordering::Less => *self.as_mut().min() = Some(new),
_ => *self.as_mut().min() = Some(old),
},
}
Poll::Pending
}
None => Poll::Ready(self.min),
}
}
}

View file

@ -53,6 +53,7 @@ mod take_while;
mod try_fold; mod try_fold;
mod try_for_each; mod try_for_each;
mod zip; mod zip;
mod min_by_key;
use all::AllFuture; use all::AllFuture;
use any::AnyFuture; use any::AnyFuture;
@ -74,6 +75,7 @@ use nth::NthFuture;
use partial_cmp::PartialCmpFuture; use partial_cmp::PartialCmpFuture;
use try_fold::TryFoldFuture; use try_fold::TryFoldFuture;
use try_for_each::TryForEeachFuture; use try_for_each::TryForEeachFuture;
use min_by_key::MinByKeyFuture;
pub use chain::Chain; pub use chain::Chain;
pub use filter::Filter; pub use filter::Filter;
@ -600,6 +602,42 @@ extension_trait! {
FilterMap::new(self, f) FilterMap::new(self, f)
} }
#[doc = r#"
Returns the element that gives the minimum value with respect to the
specified key function. If several elements are equally minimum,
the first element is returned. If the stream is empty, `None` is returned.
# Examples
```
# fn main() { async_std::task::block_on(async {
#
use std::collections::VecDeque;
use async_std::prelude::*;
let s: VecDeque<i32> = vec![1, 2, -3].into_iter().collect();
let min = s.clone().min_by_key(|x| x.abs()).await;
assert_eq!(min, Some(1));
let min = VecDeque::<isize>::new().min_by_key(|x| x.abs()).await;
assert_eq!(min, None);
#
# }) }
```
"#]
fn min_by_key<K>(
self,
key_by: K,
) -> impl Future<Output = Option<Self::Item>> [MinByKeyFuture<Self, Self::Item, K>]
where
Self: Sized,
K: FnMut(&Self::Item) -> Self::Item,
{
MinByKeyFuture::new(self, key_by)
}
#[doc = r#" #[doc = r#"
Returns the element that gives the minimum value with respect to the Returns the element that gives the minimum value with respect to the
specified comparison function. If several elements are equally minimum, specified comparison function. If several elements are equally minimum,