mirror of
https://github.com/samber/lo.git
synced 2025-09-26 20:11:13 +08:00
feat: adding EarliestBy and LatestBy functions (#489)
This commit is contained in:
36
README.md
36
README.md
@@ -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
48
find.go
@@ -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)
|
||||
|
52
find_test.go
52
find_test.go
@@ -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)
|
||||
|
Reference in New Issue
Block a user