Merge pull request #385 from yjhmelody/stream-min_by_key

add stream::min_by_key method
pull/412/head
Yoshua Wuyts 5 years ago committed by GitHub
commit 5ff4ef8dd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,60 @@
use std::cmp::Ordering;
use std::pin::Pin;
use pin_project_lite::pin_project;
use crate::future::Future;
use crate::stream::Stream;
use crate::task::{Context, Poll};
pin_project! {
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct MinByKeyFuture<S, T, K> {
#[pin]
stream: S,
min: Option<T>,
key_by: K,
}
}
impl<S, T, K> MinByKeyFuture<S, T, 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,
K: FnMut(&S::Item) -> S::Item,
S::Item: Ord,
{
type Output = Option<S::Item>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let next = futures_core::ready!(this.stream.poll_next(cx));
match next {
Some(new) => {
let new = (this.key_by)(&new);
cx.waker().wake_by_ref();
match this.min.take() {
None => *this.min = Some(new),
Some(old) => match new.cmp(&old) {
Ordering::Less => *this.min = Some(new),
_ => *this.min = Some(old),
},
}
Poll::Pending
}
None => Poll::Ready(this.min.take()),
}
}
}

@ -41,6 +41,7 @@ mod le;
mod lt;
mod map;
mod min_by;
mod min_by_key;
mod next;
mod nth;
mod partial_cmp;
@ -69,6 +70,7 @@ use last::LastFuture;
use le::LeFuture;
use lt::LtFuture;
use min_by::MinByFuture;
use min_by_key::MinByKeyFuture;
use next::NextFuture;
use nth::NthFuture;
use partial_cmp::PartialCmpFuture;
@ -680,6 +682,43 @@ extension_trait! {
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,
Self::Item: Ord,
K: FnMut(&Self::Item) -> Self::Item,
{
MinByKeyFuture::new(self, key_by)
}
#[doc = r#"
Returns the element that gives the minimum value with respect to the
specified comparison function. If several elements are equally minimum,

Loading…
Cancel
Save