diff --git a/docs/slice.md b/docs/slice.md index 7414bbb..fe51433 100644 --- a/docs/slice.md +++ b/docs/slice.md @@ -43,8 +43,10 @@ import ( - [EqualWith](#EqualWith) - [Every](#Every) - [Filter](#Filter) -- [Find](#Find) -- [FindLast](#FindLast) +- [Finddeprecated](#Find) +- [FindBy](#FindBy) +- [FindLastdeprecated](#FindLast) +- [FindLastBy](#FindLastBy) - [Flatten](#Flatten) - [FlattenDeep](#FlattenDeep) - [ForEach](#ForEach) @@ -837,7 +839,7 @@ func main() { } ``` -### Find +### Find(deprecated: use FindBy)

Iterates over elements of slice, returning the first one that passes a truth test on function.

@@ -873,7 +875,43 @@ func main() { } ``` -### FindLast +### FindBy + +

Iterates over elements of slice, returning the first one that passes a truth test on predicate function.If return T is nil or zero value then no items matched the predicate func. In contrast to Find or FindLast, its return value no longer requires dereferencing

+ +Signature: + +```go +func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/slice" +) + +func main() { + nums := []int{1, 2, 3, 4, 5} + + isEven := func(i, num int) bool { + return num%2 == 0 + } + + result, ok := slice.FindBy(nums, isEven) + + fmt.Println(result) + fmt.Println(ok) + + // Output: + // 2 + // true +} +``` + +### FindLast(deprecated: use FindLastBy)

iterates over elements of slice from end to begin, returning the last one that passes a truth test on function.

@@ -909,6 +947,42 @@ func main() { } ``` +### FindLastBy + +

FindLastBy iterates over elements of slice, returning the last one that passes a truth test on predicate function. If return T is nil or zero value then no items matched the predicate func. In contrast to Find or FindLast, its return value no longer requires dereferencing

+ +Signature: + +```go +func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/slice" +) + +func main() { + nums := []int{1, 2, 3, 4, 5} + + isEven := func(i, num int) bool { + return num%2 == 0 + } + + result, ok := slice.FindLastBy(nums, isEven) + + fmt.Println(result) + fmt.Println(ok) + + // Output: + // 4 + // true +} +``` + ### Flatten

Flatten slice with one level.

diff --git a/docs/slice_zh-CN.md b/docs/slice_zh-CN.md index 63b1a3b..d87cc67 100644 --- a/docs/slice_zh-CN.md +++ b/docs/slice_zh-CN.md @@ -43,8 +43,10 @@ import ( - [Equal](#Equal) - [EqualWith](#EqualWith) - [Filter](#Filter) -- [Find](#Find) -- [FindLast](#FindLast) +- [Finddeprecated](#Find) +- [FindBy](#FindBy) +- [FindLastdeprecated](#FindLast) +- [FindLastBy](#FindLastBy) - [Flatten](#Flatten) - [FlattenDeep](#FlattenDeep) - [ForEach](#ForEach) @@ -838,9 +840,9 @@ func main() { } ``` -### Find +### Find (废弃:使用 FindBy) -

遍历切片的元素,返回第一个通过predicate函数真值测试的元素

+

遍历slice的元素,返回第一个通过predicate函数真值测试的元素

函数签名: @@ -874,9 +876,45 @@ func main() { } ``` -### FindLast +### FindBy -

从头到尾遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。

+

遍历slice的元素,返回第一个通过predicate函数真值测试的元素

+ +函数签名: + +```go +func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/slice" +) + +func main() { + nums := []int{1, 2, 3, 4, 5} + + isEven := func(i, num int) bool { + return num%2 == 0 + } + + result, ok := slice.FindBy(nums, isEven) + + fmt.Println(result) + fmt.Println(ok) + + // Output: + // 2 + // true +} +``` + +### FindLast(废弃:使用 FindLastBy) + +

遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。

函数签名: @@ -910,6 +948,42 @@ func main() { } ``` +### FindLastBy + +

从遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。

+ +函数签名: + +```go +func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/slice" +) + +func main() { + nums := []int{1, 2, 3, 4, 5} + + isEven := func(i, num int) bool { + return num%2 == 0 + } + + result, ok := slice.FindLastBy(nums, isEven) + + fmt.Println(result) + fmt.Println(ok) + + // Output: + // 4 + // true +} +``` + ### Flatten

将切片压平一层

diff --git a/docs/strutil.md b/docs/strutil.md index 67781c1..65c6120 100644 --- a/docs/strutil.md +++ b/docs/strutil.md @@ -46,6 +46,12 @@ import ( - [SplitWords](#SplitWords) - [WordCount](#WordCount) - [RemoveNonPrintable](#RemoveNonPrintable) +- [StringToBytes](#StringToBytes) +- [BytesToString](#BytesToString) +- [IsBlank](#IsBlank) +- [HasPrefixAny](#HasPrefixAny) +- [HasSuffixAny](#HasSuffixAny) +- [IndexOffset](#IndexOffset)
@@ -852,7 +858,6 @@ func main() { } ``` - ### SplitWords

Splits a string into words, word only contains alphabetic characters.

@@ -896,7 +901,6 @@ func main() { } ``` - ### WordCount

Return the number of meaningful word, word only contains alphabetic characters.

@@ -940,7 +944,6 @@ func main() { } ``` - ### RemoveNonPrintable

Remove non-printable characters from a string.

@@ -969,4 +972,196 @@ func main() { // hello world // 你好😄 } -``` \ No newline at end of file +``` + +### StringToBytes + +

Converts a string to byte slice without a memory allocation.

+ +Signature: + +```go +func StringToBytes(str string) (b []byte) +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.StringToBytes("abc") + result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'}) + + fmt.Println(result1) + fmt.Println(result2) + // Output: + // [97 98 99] + // true +} +``` + +### BytesToString + +

Converts a byte slice to string without a memory allocation.

+ +Signature: + +```go +func BytesToString(bytes []byte) string +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + bytes := []byte{'a', 'b', 'c'} + result := strutil.BytesToString(bytes) + + fmt.Println(result) + // Output: + // abc +} +``` + +### IsBlank + +

Checks if a string is whitespace or empty.

+ +Signature: + +```go +func IsBlank(str string) bool +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.IsBlank("") + result2 := strutil.IsBlank("\t\v\f\n") + result3 := strutil.IsBlank(" 中文") + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + // Output: + // true + // true + // false +} +``` + +### HasPrefixAny + +

Checks if a string starts with any of an array of specified strings.

+ +Signature: + +```go +func HasPrefixAny(str string, prefixes []string) bool +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"}) + result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"}) + + fmt.Println(result1) + fmt.Println(result2) + // Output: + // true + // false +} +``` + +### HasSuffixAny + +

Checks if a string ends with any of an array of specified strings.

+ +Signature: + +```go +func HasSuffixAny(str string, suffixes []string) bool +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"}) + result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"}) + + fmt.Println(result1) + fmt.Println(result2) + // Output: + // true + // false +} +``` + +### IndexOffset + +

Returns the index of the first instance of substr in string after offsetting the string by `idxFrom`, or -1 if substr is not present in string.

+ +Signature: + +```go +func IndexOffset(str string, substr string, idxFrom int) int +``` + +Example: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + str := "foo bar hello world" + + result1 := strutil.IndexOffset(str, "o", 5) + result2 := strutil.IndexOffset(str, "o", 0) + result3 := strutil.IndexOffset(str, "d", len(str)-1) + result4 := strutil.IndexOffset(str, "d", len(str)) + result5 := strutil.IndexOffset(str, "f", -1) + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + fmt.Println(result4) + fmt.Println(result5) + // Output: + // 12 + // 1 + // 18 + // -1 + // -1 +} +``` diff --git a/docs/strutil_zh-CN.md b/docs/strutil_zh-CN.md index 6853eaf..f640b48 100644 --- a/docs/strutil_zh-CN.md +++ b/docs/strutil_zh-CN.md @@ -46,6 +46,12 @@ import ( - [SplitWords](#SplitWords) - [WordCount](#WordCount) - [RemoveNonPrintable](#RemoveNonPrintable) +- [StringToBytes](#StringToBytes) +- [BytesToString](#BytesToString) +- [IsBlank](#IsBlank) +- [HasPrefixAny](#HasPrefixAny) +- [HasSuffixAny](#HasSuffixAny) +- [IndexOffset](#IndexOffset)
@@ -895,7 +901,6 @@ func main() { } ``` - ### WordCount

返回有意义单词的数量,只支持字母字符单词。

@@ -939,7 +944,6 @@ func main() { } ``` - ### RemoveNonPrintable

删除字符串中不可打印的字符。

@@ -968,4 +972,196 @@ func main() { // hello world // 你好😄 } -``` \ No newline at end of file +``` + +### StringToBytes + +

在不分配内存的情况下将字符串转换为字节片。

+ +函数签名: + +```go +func StringToBytes(str string) (b []byte) +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.StringToBytes("abc") + result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'}) + + fmt.Println(result1) + fmt.Println(result2) + // Output: + // [97 98 99] + // true +} +``` + +### BytesToString + +

在不分配内存的情况下将字节切片转换为字符串。

+ +函数签名: + +```go +func BytesToString(bytes []byte) string +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + bytes := []byte{'a', 'b', 'c'} + result := strutil.BytesToString(bytes) + + fmt.Println(result) + // Output: + // abc +} +``` + +### IsBlank + +

检查字符串是否为空格或空。

+ +函数签名: + +```go +func IsBlank(str string) bool +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.IsBlank("") + result2 := strutil.IsBlank("\t\v\f\n") + result3 := strutil.IsBlank(" 中文") + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + // Output: + // true + // true + // false +} +``` + +### HasPrefixAny + +

检查字符串是否以指定字符串数组中的任何一个开头。

+ +函数签名: + +```go +func HasPrefixAny(str string, prefixes []string) bool +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"}) + result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"}) + + fmt.Println(result1) + fmt.Println(result2) + // Output: + // true + // false +} +``` + +### HasSuffixAny + +

检查字符串是否以指定字符串数组中的任何一个结尾。

+ +函数签名: + +```go +func HasSuffixAny(str string, suffixes []string) bool +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"}) + result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"}) + + fmt.Println(result1) + fmt.Println(result2) + // Output: + // true + // false +} +``` + +### IndexOffset + +

将字符串偏移idxFrom后,返回字符串中第一个 substr 实例的索引,如果字符串中不存在 substr,则返回 -1。

+ +函数签名: + +```go +func IndexOffset(str string, substr string, idxFrom int) int +``` + +示例: + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/strutil" +) + +func main() { + str := "foo bar hello world" + + result1 := strutil.IndexOffset(str, "o", 5) + result2 := strutil.IndexOffset(str, "o", 0) + result3 := strutil.IndexOffset(str, "d", len(str)-1) + result4 := strutil.IndexOffset(str, "d", len(str)) + result5 := strutil.IndexOffset(str, "f", -1) + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + fmt.Println(result4) + fmt.Println(result5) + // Output: + // 12 + // 1 + // 18 + // -1 + // -1 +} +``` diff --git a/slice/slice.go b/slice/slice.go index 39456ae..73c23ff 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -331,25 +331,14 @@ func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) { // Play: https://go.dev/play/p/FFDPV_j7URd // Deprecated func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) { - index := -1 - - for i := len(slice) - 1; i >= 0; i-- { - if predicate(i, slice[i]) { - index = i - break - } - } - - if index == -1 { - return nil, false - } - - return &slice[index], true + v, ok := FindLastBy(slice, predicate) + return &v, ok } // FindBy iterates over elements of slice, returning the first one that passes a truth test on predicate function. // If return T is nil or zero value then no items matched the predicate func. // In contrast to Find or FindLast, its return value no longer requires dereferencing +// Play: todo func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) { index := -1 @@ -370,6 +359,7 @@ func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok b // FindLastBy iterates over elements of slice, returning the last one that passes a truth test on predicate function. // If return T is nil or zero value then no items matched the predicate func. // In contrast to Find or FindLast, its return value no longer requires dereferencing +// Play: todo func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) { index := -1 diff --git a/strutil/string.go b/strutil/string.go index bb7afed..f7982b0 100644 --- a/strutil/string.go +++ b/strutil/string.go @@ -376,7 +376,8 @@ func RemoveNonPrintable(str string) string { return result } -// StringToBytes converts a string to byte slice without a memory allocation +// StringToBytes converts a string to byte slice without a memory allocation. +// Play: todo func StringToBytes(str string) (b []byte) { sh := *(*reflect.StringHeader)(unsafe.Pointer(&str)) bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) @@ -384,12 +385,14 @@ func StringToBytes(str string) (b []byte) { return b } -// BytesToString converts a byte slice to string without a memory allocation +// BytesToString converts a byte slice to string without a memory allocation. +// Play: todo func BytesToString(bytes []byte) string { return *(*string)(unsafe.Pointer(&bytes)) } -// IsBlank checks if a string is whitespace, empty +// IsBlank checks if a string is whitespace, empty. +// Play: todo func IsBlank(str string) bool { if len(str) == 0 { return true @@ -404,7 +407,8 @@ func IsBlank(str string) bool { return true } -// HasPrefixAny check if a string starts with any of an array of specified strings +// HasPrefixAny check if a string starts with any of an array of specified strings. +// Play: todo func HasPrefixAny(str string, prefixes []string) bool { if len(str) == 0 || len(prefixes) == 0 { return false @@ -417,7 +421,8 @@ func HasPrefixAny(str string, prefixes []string) bool { return false } -// HasSuffixAny check if a string ends with any of an array of specified strings +// HasSuffixAny check if a string ends with any of an array of specified strings. +// Play: todo func HasSuffixAny(str string, suffixes []string) bool { if len(str) == 0 || len(suffixes) == 0 { return false @@ -430,8 +435,9 @@ func HasSuffixAny(str string, suffixes []string) bool { return false } -// IndexOffset returns the index of the first instance of substr in s after offsetting the string by `idxFrom`, -// or -1 if substr is not present in s. +// IndexOffset returns the index of the first instance of substr in string after offsetting the string by `idxFrom`, +// or -1 if substr is not present in string. +// Play: todo func IndexOffset(str string, substr string, idxFrom int) int { if idxFrom > len(str)-1 || idxFrom < 0 { return -1