Skip to content

Commit

Permalink
add max_by_key
Browse files Browse the repository at this point in the history
  • Loading branch information
yjhmelody committed Nov 2, 2019
1 parent c413e71 commit 0ab8f78
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/stream/stream/max_by_key.rs
Original file line number Diff line number Diff line change
@@ -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()),
}
}
}
45 changes: 45 additions & 0 deletions src/stream/stream/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ mod le;
mod lt;
mod map;
mod max_by;
<<<<<<< HEAD
mod min;
=======
mod max_by_key;
>>>>>>> add max_by_key
mod min_by;
mod min_by_key;
mod ne;
Expand Down Expand Up @@ -76,7 +80,11 @@ use last::LastFuture;
use le::LeFuture;
use lt::LtFuture;
use max_by::MaxByFuture;
<<<<<<< HEAD
use min::MinFuture;
=======
use max_by_key::MaxByKeyFuture;
>>>>>>> add max_by_key
use min_by::MinByFuture;
use min_by_key::MinByKeyFuture;
use ne::NeFuture;
Expand Down Expand Up @@ -729,6 +737,43 @@ extension_trait! {
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#"
Returns the element that gives the minimum value with respect to the
specified comparison function. If several elements are equally minimum,
Expand Down

0 comments on commit 0ab8f78

Please sign in to comment.