-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: x/exp/xiter: add Max/Min/MinMax{Func} #67456
Comments
I assume these will panic on an empty sequence, similar to |
(I was surprised there wasn't a This comment applies to #67457 and #67458 as well. Sequences are sometimes safely resumable (will get the same results in the same order if you range over it again) but that's not a guaranteed property. Maybe things like this could be handled in a slightly different manner. First have a general adapter: func Tap[T any](iter.Seq[T], func(T) bool) iter.Seq[T] (and likewise for
That way you could have something like seq, info := collectMinMax(seq)
for v := range seq {
//...
}
min, max := info.MinMax() where |
Actually I suppose if it can stop the sequence early, that's identical to |
Later I thought about it carefully, panic on empty sequence is unreasonable, because we can easily judge whether slice is empty or not, but there is no reasonable way to deal with sequences. In other words, it is difficult for users to avoid panic. Therefore an extra bool is returned bool that indicating whether there is a maximum/minimum value. So the signature can change to: func Max[E cmp.Ordered](s Seq[E]) (E, bool)
func MaxFunc[E any](s Seq[E], f func(E, E) int ) (E, bool)
// So and Min/MinFunc/MinMax/MinMaxFunc. |
Here's a basic implementation of func MinMax[T cmp.Ordered](s iter.Seq[T]) (*Stats[T], iter.Seq[T]) {
stats := &Stats[T]{}
return stats, xiter.TakeWhile(stats.record, s)
}
type Stats[T cmp.Ordered] struct {
Ok bool
Min, Max T
}
func (s *Stats[T]) record(v T) bool {
if s.Ok {
s.Min, s.Max = min(s.Min, v), max(s.Max, v)
} else {
s.Ok, s.Min, s.Max = true, v, v
}
return true
} |
With #60274 it could be defined for 0-length sequences, and a bit more concisely, at the expense of no longer working on strings func MinMax[T math.Ordered](s iter.Seq[T]) (*Stats[T], iter.Seq[T]) {
stats := &Stats[T]{
Min: math.Greatest[T](),
Max: math.Least[T](),
}
return stats, xiter.TakeWhile(stats.record, s)
}
type Stats[T math.Ordered] struct {
Min, Max T
}
func (s *Stats[T]) record(v T) bool {
s.Min, s.Max = min(s.Min, v), max(s.Max, v)
return true
} |
A downside to Conversely, if a ternary function is a requirement, then it could at least leverage that to gather all equal elements. Collecting ties is a common use case, and elegantly solves the empty/panic problem. func SelectFunc[E any](s Seq[E], f func(E, E) bool) (E, bool) // cmp.Less == Min
func MinFunc[E any](s Seq[E], f func(E, E) int) []E
func MaxFunc[E any](s Seq[E], f func(E, E) int) []E I think either of those would be an improvement of the choice in |
Proposal Details
Proposed add below functions:
The text was updated successfully, but these errors were encountered: