mirror of
https://github.com/samber/lo.git
synced 2025-09-26 20:11:13 +08:00
Merge branch 'master' into feat-add-trim
This commit is contained in:
1
.github/workflows/lint.yml
vendored
1
.github/workflows/lint.yml
vendored
@@ -17,7 +17,6 @@ jobs:
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
version: 'v2.4'
|
||||
args: --timeout 120s --max-same-issues 50
|
||||
|
||||
- name: Bearer
|
||||
|
@@ -129,7 +129,7 @@ func Try(callback func() error) (ok bool) {
|
||||
ok = false
|
||||
}
|
||||
|
||||
return
|
||||
return ok
|
||||
}
|
||||
|
||||
// Try0 has the same behavior as Try, but callback returns no variable.
|
||||
@@ -327,7 +327,7 @@ func TryWithErrorValue(callback func() error) (errorValue any, ok bool) {
|
||||
errorValue = err
|
||||
}
|
||||
|
||||
return
|
||||
return errorValue, ok
|
||||
}
|
||||
|
||||
// TryCatch has the same behavior as Try, but calls the catch function in case of error.
|
||||
|
10
slice.go
10
slice.go
@@ -113,7 +113,7 @@ func ForEach[T any](collection []T, iteratee func(item T, index int)) {
|
||||
// ForEachWhile iterates over elements of collection and invokes iteratee for each element
|
||||
// collection return value decide to continue or break, like do while().
|
||||
// Play: https://go.dev/play/p/QnLGt35tnow
|
||||
func ForEachWhile[T any](collection []T, iteratee func(item T, index int) (goon bool)) {
|
||||
func ForEachWhile[T any](collection []T, iteratee func(item T, index int) bool) {
|
||||
for i := range collection {
|
||||
if !iteratee(collection[i], i) {
|
||||
break
|
||||
@@ -571,7 +571,9 @@ func FilterReject[T any, Slice ~[]T](collection Slice, predicate func(T, int) bo
|
||||
|
||||
// Count counts the number of elements in the collection that equal value.
|
||||
// Play: https://go.dev/play/p/Y3FlK54yveC
|
||||
func Count[T comparable](collection []T, value T) (count int) {
|
||||
func Count[T comparable](collection []T, value T) int {
|
||||
var count int
|
||||
|
||||
for i := range collection {
|
||||
if collection[i] == value {
|
||||
count++
|
||||
@@ -583,7 +585,9 @@ func Count[T comparable](collection []T, value T) (count int) {
|
||||
|
||||
// CountBy counts the number of elements in the collection for which predicate is true.
|
||||
// Play: https://go.dev/play/p/ByQbNYQQi4X
|
||||
func CountBy[T any](collection []T, predicate func(item T) bool) (count int) {
|
||||
func CountBy[T any](collection []T, predicate func(item T) bool) int {
|
||||
var count int
|
||||
|
||||
for i := range collection {
|
||||
if predicate(collection[i]) {
|
||||
count++
|
||||
|
@@ -1133,36 +1133,43 @@ func TestSplice(t *testing.T) {
|
||||
func TestCutSuccess(t *testing.T) {
|
||||
t.Parallel()
|
||||
is := assert.New(t)
|
||||
|
||||
// case 1
|
||||
actualLeft, actualRight, result := Cut([]string{"a", "b", "c", "d", "e", "f", "g"}, []string{"a", "b"})
|
||||
is.True(result)
|
||||
is.Equal([]string{}, actualLeft)
|
||||
is.Equal([]string{"c", "d", "e", "f", "g"}, actualRight)
|
||||
|
||||
// case 2
|
||||
actualLeft, actualRight, result = Cut([]string{"a", "b", "c", "d", "e", "f", "g"}, []string{"f", "g"})
|
||||
is.True(result)
|
||||
is.Equal([]string{"a", "b", "c", "d", "e"}, actualLeft)
|
||||
is.Equal([]string{}, actualRight)
|
||||
|
||||
// case 3
|
||||
actualLeft, actualRight, result = Cut([]string{"g"}, []string{"g"})
|
||||
is.True(result)
|
||||
is.Equal([]string{}, actualLeft)
|
||||
is.Equal([]string{}, actualRight)
|
||||
|
||||
// case 4
|
||||
actualLeft, actualRight, result = Cut([]string{"a", "b", "c", "d", "e", "f", "g"}, []string{"b", "c"})
|
||||
is.True(result)
|
||||
is.Equal([]string{"a"}, actualLeft)
|
||||
is.Equal([]string{"d", "e", "f", "g"}, actualRight)
|
||||
|
||||
// case 5
|
||||
actualLeft, actualRight, result = Cut([]string{"a", "b", "c", "d", "e", "f", "g"}, []string{"e", "f"})
|
||||
is.True(result)
|
||||
is.Equal([]string{"a", "b", "c", "d"}, actualLeft)
|
||||
is.Equal([]string{"g"}, actualRight)
|
||||
|
||||
// case 6
|
||||
actualLeft, actualRight, result = Cut([]string{"a", "b"}, []string{"b"})
|
||||
is.True(result)
|
||||
is.Equal([]string{"a"}, actualLeft)
|
||||
is.Equal([]string{}, actualRight)
|
||||
|
||||
// case 7
|
||||
actualLeft, actualRight, result = Cut([]string{"a", "b"}, []string{"a"})
|
||||
is.True(result)
|
||||
@@ -1173,16 +1180,19 @@ func TestCutSuccess(t *testing.T) {
|
||||
func TestCutFail(t *testing.T) {
|
||||
t.Parallel()
|
||||
is := assert.New(t)
|
||||
|
||||
// case 1
|
||||
actualLeft, actualRight, result := Cut([]string{"a", "b", "c", "d", "e", "f", "g"}, []string{"z"})
|
||||
is.False(result)
|
||||
is.Equal([]string{"a", "b", "c", "d", "e", "f", "g"}, actualLeft)
|
||||
is.Equal([]string{}, actualRight)
|
||||
|
||||
// case 2
|
||||
actualLeft, actualRight, result = Cut([]string{}, []string{"z"})
|
||||
is.False(result)
|
||||
is.Equal([]string{}, actualLeft)
|
||||
is.Equal([]string{}, actualRight)
|
||||
|
||||
// case 3
|
||||
actualLeft, actualRight, result = Cut([]string{"a"}, []string{"z"})
|
||||
is.False(result)
|
||||
@@ -1198,6 +1208,7 @@ type TestCutStruct struct {
|
||||
func TestCutPrefix(t *testing.T) {
|
||||
t.Parallel()
|
||||
is := assert.New(t)
|
||||
|
||||
// case 1
|
||||
actualAfter, result := CutPrefix(
|
||||
[]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}},
|
||||
@@ -1205,6 +1216,7 @@ func TestCutPrefix(t *testing.T) {
|
||||
)
|
||||
is.True(result)
|
||||
is.Equal([]TestCutStruct{{id: 2, data: "a"}, {id: 2, data: "b"}}, actualAfter)
|
||||
|
||||
// case 2
|
||||
actualAfter, result = CutPrefix(
|
||||
[]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}},
|
||||
@@ -1212,6 +1224,7 @@ func TestCutPrefix(t *testing.T) {
|
||||
)
|
||||
is.True(result)
|
||||
is.Equal([]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}}, actualAfter)
|
||||
|
||||
// case 3
|
||||
actualAfter, result = CutPrefix(
|
||||
[]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}},
|
||||
@@ -1219,6 +1232,7 @@ func TestCutPrefix(t *testing.T) {
|
||||
)
|
||||
is.False(result)
|
||||
is.Equal([]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}}, actualAfter)
|
||||
|
||||
// case 4
|
||||
actualAfter, result = CutPrefix(
|
||||
[]TestCutStruct{},
|
||||
@@ -1226,6 +1240,7 @@ func TestCutPrefix(t *testing.T) {
|
||||
)
|
||||
is.False(result)
|
||||
is.Equal([]TestCutStruct{}, actualAfter)
|
||||
|
||||
// case 5
|
||||
actualAfterS, result := CutPrefix([]string{"a", "a", "b"}, []string{})
|
||||
is.True(result)
|
||||
@@ -1235,6 +1250,7 @@ func TestCutPrefix(t *testing.T) {
|
||||
func TestCutSuffix(t *testing.T) {
|
||||
t.Parallel()
|
||||
is := assert.New(t)
|
||||
|
||||
// case 1
|
||||
actualBefore, result := CutSuffix(
|
||||
[]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}},
|
||||
@@ -1242,6 +1258,7 @@ func TestCutSuffix(t *testing.T) {
|
||||
)
|
||||
is.False(result)
|
||||
is.Equal([]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}}, actualBefore)
|
||||
|
||||
// case 2
|
||||
actualBefore, result = CutSuffix(
|
||||
[]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}},
|
||||
@@ -1249,6 +1266,7 @@ func TestCutSuffix(t *testing.T) {
|
||||
)
|
||||
is.True(result)
|
||||
is.Equal([]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}}, actualBefore)
|
||||
|
||||
// case 3
|
||||
actualBefore, result = CutSuffix(
|
||||
[]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}},
|
||||
@@ -1256,6 +1274,7 @@ func TestCutSuffix(t *testing.T) {
|
||||
)
|
||||
is.True(result)
|
||||
is.Equal([]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}}, actualBefore)
|
||||
|
||||
// case 4
|
||||
actualBefore, result = CutSuffix(
|
||||
[]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}},
|
||||
@@ -1263,6 +1282,7 @@ func TestCutSuffix(t *testing.T) {
|
||||
)
|
||||
is.False(result)
|
||||
is.Equal([]TestCutStruct{{id: 1, data: "a"}, {id: 2, data: "a"}, {id: 2, data: "b"}}, actualBefore)
|
||||
|
||||
// case 5
|
||||
actualAfterS, result := CutSuffix([]string{"a", "a", "b"}, []string{})
|
||||
is.True(result)
|
||||
|
@@ -506,7 +506,7 @@ func TestUnzipBy(t *testing.T) {
|
||||
t.Parallel()
|
||||
is := assert.New(t)
|
||||
|
||||
r1, r2 := UnzipBy2([]Tuple2[string, int]{{A: "a", B: 1}, {A: "b", B: 2}}, func(i Tuple2[string, int]) (a string, b int) {
|
||||
r1, r2 := UnzipBy2([]Tuple2[string, int]{{A: "a", B: 1}, {A: "b", B: 2}}, func(i Tuple2[string, int]) (string, int) {
|
||||
return i.A + i.A, i.B + i.B
|
||||
})
|
||||
|
||||
|
@@ -115,11 +115,12 @@ func FromAnySlice[T any](in []any) (out []T, ok bool) {
|
||||
}
|
||||
}()
|
||||
|
||||
result := make([]T, len(in))
|
||||
out = make([]T, len(in))
|
||||
ok = true
|
||||
for i := range in {
|
||||
result[i] = in[i].(T) //nolint:errcheck,forcetypeassert
|
||||
out[i] = in[i].(T) //nolint:errcheck,forcetypeassert
|
||||
}
|
||||
return result, true
|
||||
return out, ok
|
||||
}
|
||||
|
||||
// Empty returns the zero value (https://go.dev/ref/spec#The_zero_value).
|
||||
@@ -145,16 +146,16 @@ func IsNotEmpty[T comparable](v T) bool {
|
||||
|
||||
// Coalesce returns the first non-empty arguments. Arguments must be comparable.
|
||||
// Play: https://go.dev/play/p/Gyo9otyvFHH
|
||||
func Coalesce[T comparable](values ...T) (result T, ok bool) {
|
||||
func Coalesce[T comparable](values ...T) (T, bool) {
|
||||
var zero T
|
||||
|
||||
for i := range values {
|
||||
if values[i] != result {
|
||||
result = values[i]
|
||||
ok = true
|
||||
return
|
||||
if values[i] != zero {
|
||||
return values[i], true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return zero, false
|
||||
}
|
||||
|
||||
// CoalesceOrEmpty returns the first non-empty arguments. Arguments must be comparable.
|
||||
|
Reference in New Issue
Block a user