feat: adding EarliestBy and LatestBy functions (#489)

This commit is contained in:
Timur Polukeev
2024-07-13 16:41:15 +02:00
committed by GitHub
parent d93dd9a2d7
commit 34537d5291
3 changed files with 136 additions and 0 deletions

View File

@@ -222,9 +222,11 @@ Supported search helpers:
- [Min](#min)
- [MinBy](#minby)
- [Earliest](#earliest)
- [EarliestBy](#earliestby)
- [Max](#max)
- [MaxBy](#maxby)
- [Latest](#latest)
- [LatestBy](#latestby)
- [First](#first)
- [FirstOrEmpty](#FirstOrEmpty)
- [FirstOr](#FirstOr)
@@ -2260,6 +2262,23 @@ earliest := lo.Earliest(time.Now(), time.Time{})
// 0001-01-01 00:00:00 +0000 UTC
```
### EarliestBy
Search the minimum time.Time of a collection using the given iteratee function.
Returns zero value when the collection is empty.
```go
type foo struct {
bar time.Time
}
earliest := lo.EarliestBy([]foo{{time.Now()}, {}}, func(i foo) time.Time {
return i.bar
})
// {bar:{2023-04-01 01:02:03 +0000 UTC}}
```
### Max
Search the maximum value of a collection.
@@ -2308,6 +2327,23 @@ latest := lo.Latest([]time.Time{time.Now(), time.Time{}})
// 2023-04-01 01:02:03 +0000 UTC
```
### LatestBy
Search the maximum time.Time of a collection using the given iteratee function.
Returns zero value when the collection is empty.
```go
type foo struct {
bar time.Time
}
latest := lo.LatestBy([]foo{{time.Now()}, {}}, func(i foo) time.Time {
return i.bar
})
// {bar:{2023-04-01 01:02:03 +0000 UTC}}
```
### First
Returns the first element of a collection and check for availability of the first element.

48
find.go
View File

@@ -286,6 +286,30 @@ func Earliest(times ...time.Time) time.Time {
return min
}
// EarliestBy search the minimum time.Time of a collection using the given iteratee function.
// Returns zero value when the collection is empty.
func EarliestBy[T any](collection []T, iteratee func(item T) time.Time) T {
var earliest T
if len(collection) == 0 {
return earliest
}
earliest = collection[0]
earliestTime := iteratee(collection[0])
for i := 1; i < len(collection); i++ {
itemTime := iteratee(collection[i])
if itemTime.Before(earliestTime) {
earliest = collection[i]
earliestTime = itemTime
}
}
return earliest
}
// Max searches the maximum value of a collection.
// Returns zero value when the collection is empty.
func Max[T constraints.Ordered](collection []T) T {
@@ -353,6 +377,30 @@ func Latest(times ...time.Time) time.Time {
return max
}
// LatestBy search the maximum time.Time of a collection using the given iteratee function.
// Returns zero value when the collection is empty.
func LatestBy[T any](collection []T, iteratee func(item T) time.Time) T {
var latest T
if len(collection) == 0 {
return latest
}
latest = collection[0]
latestTime := iteratee(collection[0])
for i := 1; i < len(collection); i++ {
itemTime := iteratee(collection[i])
if itemTime.After(latestTime) {
latest = collection[i]
latestTime = itemTime
}
}
return latest
}
// First returns the first element of a collection and check for availability of the first element.
func First[T any](collection []T) (T, bool) {
length := len(collection)

View File

@@ -336,6 +336,32 @@ func TestEarliest(t *testing.T) {
is.Equal(result2, time.Time{})
}
func TestEarliestBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
type foo struct {
bar time.Time
}
t1 := time.Now()
t2 := t1.Add(time.Hour)
t3 := t1.Add(-time.Hour)
result1 := EarliestBy([]foo{{t1}, {t2}, {t3}}, func(i foo) time.Time {
return i.bar
})
result2 := EarliestBy([]foo{{t1}}, func(i foo) time.Time {
return i.bar
})
result3 := EarliestBy([]foo{}, func(i foo) time.Time {
return i.bar
})
is.Equal(result1, foo{t3})
is.Equal(result2, foo{t1})
is.Equal(result3, foo{})
}
func TestMax(t *testing.T) {
t.Parallel()
is := assert.New(t)
@@ -383,6 +409,32 @@ func TestLatest(t *testing.T) {
is.Equal(result2, time.Time{})
}
func TestLatestBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
type foo struct {
bar time.Time
}
t1 := time.Now()
t2 := t1.Add(time.Hour)
t3 := t1.Add(-time.Hour)
result1 := LatestBy([]foo{{t1}, {t2}, {t3}}, func(i foo) time.Time {
return i.bar
})
result2 := LatestBy([]foo{{t1}}, func(i foo) time.Time {
return i.bar
})
result3 := LatestBy([]foo{}, func(i foo) time.Time {
return i.bar
})
is.Equal(result1, foo{t2})
is.Equal(result2, foo{t1})
is.Equal(result3, foo{})
}
func TestFirst(t *testing.T) {
t.Parallel()
is := assert.New(t)