Skip to content
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

feat: adding EarliestBy and LatestBy functions #489

Merged
merged 1 commit into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
48 changes: 48 additions & 0 deletions find.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
52 changes: 52 additions & 0 deletions find_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Loading