From 5aa64ef28065731ccf3472b016d3079d5ee341b3 Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Fri, 28 Jun 2024 00:46:42 +0200 Subject: [PATCH] feat: adding LastOrEmpty and LastOr (#474) --- README.md | 50 +++++++++++++++++++++++++++++++++++++++++--------- find.go | 42 +++++++++++++++++++++++++++++------------- find_test.go | 52 +++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 109 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 5b96c371..2097c3da 100644 --- a/README.md +++ b/README.md @@ -222,10 +222,12 @@ Supported search helpers: - [Max](#max) - [MaxBy](#maxby) - [Latest](#latest) -- [Last](#last) - [First](#first) - [FirstOrEmpty](#FirstOrEmpty) - [FirstOr](#FirstOr) +- [Last](#last) +- [LastOrEmpty](#LastOrEmpty) +- [LastOr](#LastOr) - [Nth](#nth) - [Sample](#sample) - [Samples](#samples) @@ -2238,14 +2240,6 @@ latest := lo.Latest([]time.Time{time.Now(), time.Time{}}) // 2023-04-01 01:02:03 +0000 UTC ``` -### Last - -Returns the last element of a collection or error if empty. - -```go -last, err := lo.Last([]int{1, 2, 3}) -// 3 -``` ### First Returns the first element of a collection and check for availability of the first element. @@ -2257,6 +2251,7 @@ first, ok := lo.First([]int{1, 2, 3}) first, ok := lo.First([]int{}) // 0, false ``` + ### FirstOrEmpty Returns the first element of a collection or zero value if empty. @@ -2280,6 +2275,43 @@ first := lo.FirstOr([]int{}, 31) // 31 ``` +### Last + +Returns the last element of a collection or error if empty. + +```go +last, ok := lo.Last([]int{1, 2, 3}) +// 3 +// true + +last, ok := lo.Last([]int{}) +// 0 +// false +``` + +### FirstOrEmpty + +Returns the first element of a collection or zero value if empty. + +```go +last := lo.LastOrEmpty([]int{1, 2, 3}) +// 3 + +last := lo.LastOrEmpty([]int{}) +// 0 +``` +### FirstOr + +Returns the first element of a collection or the fallback value if empty. + +```go +last := lo.LastOr([]int{1, 2, 3}, 245) +// 3 + +last := lo.LastOr([]int{}, 31) +// 31 +``` + ### Nth Returns the element at index `nth` of collection. If `nth` is negative, the nth element from the end is returned. An error is returned when nth is out of slice bounds. diff --git a/find.go b/find.go index 542e01d7..3cbefad2 100644 --- a/find.go +++ b/find.go @@ -355,20 +355,36 @@ func Latest(times ...time.Time) time.Time { return max } -// Last returns the last element of a collection or error if empty. -func Last[T any](collection []T) (T, error) { +// 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) if length == 0 { var t T - return t, fmt.Errorf("last: cannot extract the last element of an empty slice") + return t, false } - return collection[length-1], nil + return collection[0], true } -// Returns the first element of a collection and check for availability of the first element. -func First[T any](collection []T) (T, bool) { +// FirstOrEmpty returns the first element of a collection or zero value if empty. +func FirstOrEmpty[T any](collection []T) T { + i, _ := First(collection) + return i +} + +// FirstOr returns the first element of a collection or the fallback value if empty. +func FirstOr[T any](collection []T, fallback T) T { + i, ok := First(collection) + if !ok { + return fallback + } + + return i +} + +// Last returns the last element of a collection or error if empty. +func Last[T any](collection []T) (T, bool) { length := len(collection) if length == 0 { @@ -376,18 +392,18 @@ func First[T any](collection []T) (T, bool) { return t, false } - return collection[0], true + return collection[length-1], true } -// Returns the first element of a collection or zero value if empty. -func FirstOrEmpty[T any](collection []T) T { - i, _ := First(collection) +// Returns the last element of a collection or zero value if empty. +func LastOrEmpty[T any](collection []T) T { + i, _ := Last(collection) return i } -// Returns the first element of a collection or the fallback value if empty. -func FirstOr[T any](collection []T, fallback T) T { - i, ok := First(collection) +// LastOr returns the last element of a collection or the fallback value if empty. +func LastOr[T any](collection []T, fallback T) T { + i, ok := Last(collection) if !ok { return fallback } diff --git a/find_test.go b/find_test.go index 8f9fe325..907004ec 100644 --- a/find_test.go +++ b/find_test.go @@ -359,19 +359,6 @@ func TestLatest(t *testing.T) { is.Equal(result2, time.Time{}) } -func TestLast(t *testing.T) { - t.Parallel() - is := assert.New(t) - - result1, err1 := Last([]int{1, 2, 3}) - result2, err2 := Last([]int{}) - - is.Equal(result1, 3) - is.Equal(err1, nil) - is.Equal(result2, 0) - is.Equal(err2, fmt.Errorf("last: cannot extract the last element of an empty slice")) -} - func TestFirst(t *testing.T) { t.Parallel() is := assert.New(t) @@ -411,6 +398,45 @@ func TestFirstOr(t *testing.T) { is.Equal(result3, "test") } +func TestLast(t *testing.T) { + t.Parallel() + is := assert.New(t) + + result1, ok1 := Last([]int{1, 2, 3}) + result2, ok2 := Last([]int{}) + + is.Equal(result1, 3) + is.True(ok1) + is.Equal(result2, 0) + is.False(ok2) +} + +func TestLastOrEmpty(t *testing.T) { + t.Parallel() + is := assert.New(t) + + result1 := LastOrEmpty([]int{1, 2, 3}) + result2 := LastOrEmpty([]int{}) + result3 := LastOrEmpty([]string{}) + + is.Equal(result1, 3) + is.Equal(result2, 0) + is.Equal(result3, "") +} + +func TestLastOr(t *testing.T) { + t.Parallel() + is := assert.New(t) + + result1 := LastOr([]int{1, 2, 3}, 63) + result2 := LastOr([]int{}, 23) + result3 := LastOr([]string{}, "test") + + is.Equal(result1, 3) + is.Equal(result2, 23) + is.Equal(result3, "test") +} + func TestNth(t *testing.T) { t.Parallel() is := assert.New(t)