add max_by_key (#408)

* add max_by_key

* fix conflict

* fmt code
poc-serde-support
yjh 5 years ago committed by Stjepan Glavina
parent 5fb9d3e980
commit 3a2e6d5b92

@ -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 MaxByKeyFuture<S, T, K> {
#[pin]
stream: S,
max: Option<T>,
key_by: K,
}
}
impl<S, T, K> MaxByKeyFuture<S, T, K> {
pub(super) fn new(stream: S, key_by: K) -> Self {
Self {
stream,
max: None,
key_by,
}
}
}
impl<S, K> Future for MaxByKeyFuture<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.max.take() {
None => *this.max = Some(new),
Some(old) => match new.cmp(&old) {
Ordering::Greater => *this.max = Some(new),
_ => *this.max = Some(old),
},
}
Poll::Pending
}
None => Poll::Ready(this.max.take()),
}
}
}

@ -43,6 +43,7 @@ mod le;
mod lt; mod lt;
mod map; mod map;
mod max_by; mod max_by;
mod max_by_key;
mod min; mod min;
mod min_by; mod min_by;
mod min_by_key; mod min_by_key;
@ -77,6 +78,7 @@ use last::LastFuture;
use le::LeFuture; use le::LeFuture;
use lt::LtFuture; use lt::LtFuture;
use max_by::MaxByFuture; use max_by::MaxByFuture;
use max_by_key::MaxByKeyFuture;
use min::MinFuture; use min::MinFuture;
use min_by::MinByFuture; use min_by::MinByFuture;
use min_by_key::MinByKeyFuture; use min_by_key::MinByKeyFuture;
@ -767,6 +769,43 @@ extension_trait! {
MinByKeyFuture::new(self, key_by) MinByKeyFuture::new(self, key_by)
} }
#[doc = r#"
Returns the element that gives the maximum value with respect to the
specified key function. If several elements are equally maximum,
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 max = s.clone().max_by_key(|x| x.abs()).await;
assert_eq!(max, Some(3));
let max = VecDeque::<isize>::new().max_by_key(|x| x.abs()).await;
assert_eq!(max, None);
#
# }) }
```
"#]
fn max_by_key<K>(
self,
key_by: K,
) -> impl Future<Output = Option<Self::Item>> [MaxByKeyFuture<Self, Self::Item, K>]
where
Self: Sized,
Self::Item: Ord,
K: FnMut(&Self::Item) -> Self::Item,
{
MaxByKeyFuture::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,

Loading…
Cancel
Save