Skip to content

Commit 0ab8f78

Browse files
committed
add max_by_key
1 parent c413e71 commit 0ab8f78

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

src/stream/stream/max_by_key.rs

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use std::cmp::Ordering;
2+
use std::pin::Pin;
3+
4+
use pin_project_lite::pin_project;
5+
6+
use crate::future::Future;
7+
use crate::stream::Stream;
8+
use crate::task::{Context, Poll};
9+
10+
pin_project! {
11+
#[doc(hidden)]
12+
#[allow(missing_debug_implementations)]
13+
pub struct MaxByKeyFuture<S, T, K> {
14+
#[pin]
15+
stream: S,
16+
max: Option<T>,
17+
key_by: K,
18+
}
19+
}
20+
21+
impl<S, T, K> MaxByKeyFuture<S, T, K> {
22+
pub(super) fn new(stream: S, key_by: K) -> Self {
23+
Self {
24+
stream,
25+
max: None,
26+
key_by,
27+
}
28+
}
29+
}
30+
31+
impl<S, K> Future for MaxByKeyFuture<S, S::Item, K>
32+
where
33+
S: Stream,
34+
K: FnMut(&S::Item) -> S::Item,
35+
S::Item: Ord,
36+
{
37+
type Output = Option<S::Item>;
38+
39+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
40+
let this = self.project();
41+
let next = futures_core::ready!(this.stream.poll_next(cx));
42+
43+
match next {
44+
Some(new) => {
45+
let new = (this.key_by)(&new);
46+
cx.waker().wake_by_ref();
47+
match this.max.take() {
48+
None => *this.max = Some(new),
49+
50+
Some(old) => match new.cmp(&old) {
51+
Ordering::Greater => *this.max = Some(new),
52+
_ => *this.max = Some(old),
53+
},
54+
}
55+
Poll::Pending
56+
}
57+
None => Poll::Ready(this.max.take()),
58+
}
59+
}
60+
}

src/stream/stream/mod.rs

+45
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ mod le;
4242
mod lt;
4343
mod map;
4444
mod max_by;
45+
<<<<<<< HEAD
4546
mod min;
47+
=======
48+
mod max_by_key;
49+
>>>>>>> add max_by_key
4650
mod min_by;
4751
mod min_by_key;
4852
mod ne;
@@ -76,7 +80,11 @@ use last::LastFuture;
7680
use le::LeFuture;
7781
use lt::LtFuture;
7882
use max_by::MaxByFuture;
83+
<<<<<<< HEAD
7984
use min::MinFuture;
85+
=======
86+
use max_by_key::MaxByKeyFuture;
87+
>>>>>>> add max_by_key
8088
use min_by::MinByFuture;
8189
use min_by_key::MinByKeyFuture;
8290
use ne::NeFuture;
@@ -729,6 +737,43 @@ extension_trait! {
729737
MinByKeyFuture::new(self, key_by)
730738
}
731739

740+
#[doc = r#"
741+
Returns the element that gives the maximum value with respect to the
742+
specified key function. If several elements are equally maximum,
743+
the first element is returned. If the stream is empty, `None` is returned.
744+
745+
# Examples
746+
747+
```
748+
# fn main() { async_std::task::block_on(async {
749+
#
750+
use std::collections::VecDeque;
751+
752+
use async_std::prelude::*;
753+
754+
let s: VecDeque<i32> = vec![-1, -2, -3].into_iter().collect();
755+
756+
let max = s.clone().max_by_key(|x| x.abs()).await;
757+
assert_eq!(max, Some(3));
758+
759+
let max = VecDeque::<isize>::new().max_by_key(|x| x.abs()).await;
760+
assert_eq!(max, None);
761+
#
762+
# }) }
763+
```
764+
"#]
765+
fn max_by_key<K>(
766+
self,
767+
key_by: K,
768+
) -> impl Future<Output = Option<Self::Item>> [MaxByKeyFuture<Self, Self::Item, K>]
769+
where
770+
Self: Sized,
771+
Self::Item: Ord,
772+
K: FnMut(&Self::Item) -> Self::Item,
773+
{
774+
MaxByKeyFuture::new(self, key_by)
775+
}
776+
732777
#[doc = r#"
733778
Returns the element that gives the minimum value with respect to the
734779
specified comparison function. If several elements are equally minimum,

0 commit comments

Comments
 (0)