Skip to content

Commit

Permalink
improve string operation and fix PadStart and PadEnd
Browse files Browse the repository at this point in the history
  • Loading branch information
A-yon Lee committed Nov 12, 2023
1 parent a107db3 commit 76359cb
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 45 deletions.
6 changes: 6 additions & 0 deletions stringx/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,21 @@ func ExamplePadStart() {
str4 := stringx.PadStart(str1, 15, "Hi")
str5 := stringx.PadStart(str1, 15, "Hola")
str6 := stringx.PadStart(str1, 12, "**")
str7 := stringx.PadStart(str1, 18, "Hola")

fmt.Printf("%#v\n", str2)
fmt.Println(str3)
fmt.Println(str4)
fmt.Println(str5)
fmt.Println(str6)
fmt.Println(str7)
// Output:
// " Hello, World!"
// **Hello, World!
// HiHello, World!
// HoHello, World!
// Hello, World!
// HolaHHello, World!
}

func ExamplePadEnd() {
Expand All @@ -63,18 +66,21 @@ func ExamplePadEnd() {
str4 := stringx.PadEnd(str1, 15, "Hi")
str5 := stringx.PadEnd(str1, 15, "Hola")
str6 := stringx.PadEnd(str1, 12, "**")
str7 := stringx.PadEnd(str1, 18, "Hola")

fmt.Printf("%#v\n", str2)
fmt.Println(str3)
fmt.Println(str4)
fmt.Println(str5)
fmt.Println(str6)
fmt.Println(str7)
// Output:
// "Hello, World! "
// Hello, World!**
// Hello, World!Hi
// Hello, World!Ho
// Hello, World!
// Hello, World!HolaH
}

func ExampleCapitalize() {
Expand Down
6 changes: 6 additions & 0 deletions stringx/mbstring/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,21 @@ func ExamplePadStart() {
str4 := mbstring.PadStart(str1, 8, "Hi")
str5 := mbstring.PadStart(str1, 8, "Hola")
str6 := mbstring.PadStart(str1, 5, "**")
str7 := mbstring.PadStart(str1, 12, "Hola")

fmt.Printf("%#v\n", str2)
fmt.Println(str3)
fmt.Println(str4)
fmt.Println(str5)
fmt.Println(str6)
fmt.Println(str7)
// Output:
// " 你好,世界!"
// **你好,世界!
// Hi你好,世界!
// Ho你好,世界!
// 你好,世界!
// HolaHo你好,世界!
}

func ExamplePadEnd() {
Expand All @@ -126,18 +129,21 @@ func ExamplePadEnd() {
str4 := mbstring.PadEnd(str1, 8, "Hi")
str5 := mbstring.PadEnd(str1, 8, "Hola")
str6 := mbstring.PadEnd(str1, 5, "**")
str7 := mbstring.PadEnd(str1, 12, "Hola")

fmt.Printf("%#v\n", str2)
fmt.Println(str3)
fmt.Println(str4)
fmt.Println(str5)
fmt.Println(str6)
fmt.Println(str7)
// Output:
// "你好,世界! "
// 你好,世界!**
// 你好,世界!Hi
// 你好,世界!Ho
// 你好,世界!
// 你好,世界!HolaHo
}

func ExampleSlice() {
Expand Down
88 changes: 57 additions & 31 deletions stringx/mbstring/mbstring.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package mbstring
import (
"math"
"slices"
"strings"
"unicode/utf8"

"github.com/ayonli/goext/slicex"
Expand All @@ -21,8 +20,13 @@ func At(str string, i int) string {
return ""
}

char, _ := slicex.At(strings.Split(str, ""), i)
return char
code, ok := slicex.At([]rune(str), i)

if ok {
return string(code)
} else {
return ""
}
}

// Returns the index at which a given sub string can be found in the string, or -1 if it is not
Expand All @@ -36,8 +40,8 @@ func Index(str string, sub string) int {
}
}

chars := strings.Split(str, "")
subChars := strings.Split(sub, "")
chars := []rune(str)
subChars := []rune(sub)
length := len(subChars)
limit := len(chars)

Expand All @@ -46,7 +50,7 @@ func Index(str string, sub string) int {

if end > limit {
break
} else if strings.Join(chars[i:i+length], "") == sub {
} else if slices.Equal(chars[i:i+length], subChars) {
return i
}
}
Expand All @@ -65,8 +69,8 @@ func LastIndex(str string, sub string) int {
}
}

chars := strings.Split(str, "")
subChars := strings.Split(sub, "")
chars := []rune(str)
subChars := []rune(sub)
length := len(subChars)
limit := len(chars)

Expand All @@ -89,41 +93,63 @@ func Length(str string) int {
// Pads the given string with another string (multiple times, if needed) until the resulting string
// reaches the final length. The padding is applied from the start of the string.
func PadStart(str string, finalLength int, padStr string) string {
leftLength := finalLength - Length(str)
padLength := finalLength - Length(str)

if leftLength <= 0 {
if padLength <= 0 {
return str
}

if Length(padStr) > leftLength {
padStr = Slice(padStr, 0, leftLength)
padChars := []rune(padStr)

if len(padChars) > padLength {
padChars = slicex.Slice(padChars, 0, padLength)
}

for Length(str) < finalLength {
str = padStr + str
padCharsLimit := len(padChars) - 1
startChars := make([]rune, padLength)

for i, j := 0, 0; i < padLength; i++ {
startChars[i] = padChars[j]

if j < padCharsLimit {
j++
} else {
j = 0
}
}

return str
return string(startChars) + str
}

// Pads the given string with another string (multiple times, if needed) until the resulting string
// reaches the final length. The padding is applied from the end of the string.
func PadEnd(str string, finalLength int, padStr string) string {
leftLength := finalLength - Length(str)
padLength := finalLength - Length(str)

if leftLength <= 0 {
if padLength <= 0 {
return str
}

if Length(padStr) > leftLength {
padStr = Slice(padStr, 0, leftLength)
padChars := []rune(padStr)

if len(padChars) > padLength {
padChars = slicex.Slice(padChars, 0, padLength)
}

for Length(str) < finalLength {
str += padStr
padCharsLimit := len(padChars) - 1
endChars := make([]rune, padLength)

for i, j := 0, 0; i < padLength; i++ {
endChars[i] = padChars[j]

if j < padCharsLimit {
j++
} else {
j = 0
}
}

return str
return str + string(endChars)
}

// Returns a section of the string selected from `start` to `end` (excluded).
Expand All @@ -132,15 +158,16 @@ func PadEnd(str string, finalLength int, padStr string) string {
//
// If `end < 0`, it will be calculated as `Length(str) + end`.
func Slice(str string, start int, end int) string {
chars := strings.Split(str, "")
return strings.Join(slicex.Slice(chars, start, end), "")
chars := []rune(str)
return string(slicex.Slice(chars, start, end))
}

// Returns a section of the string selected from `start` to `end` (excluded).
//
// This function is similar to the `Slice()`, except it doesn't accept negative positions.
func Substring(str string, start int, end int) string {
limit := Length(str)
chars := []rune(str)
limit := len(chars)

if start < 0 {
start = 0
Expand All @@ -158,13 +185,12 @@ func Substring(str string, start int, end int) string {
return "" // return an empty string directly
}

chars := strings.Split(str, "")
return strings.Join(chars[start:end], "")
return string(chars[start:end])
}

// Breaks the string into smaller chunks according to the given length.
func Chunk(str string, length int) []string {
chars := strings.Split(str, "")
chars := []rune(str)
limit := len(chars)
size := int(math.Ceil(float64(limit) / float64(length)))
chunks := make([]string, size)
Expand All @@ -178,7 +204,7 @@ func Chunk(str string, length int) []string {
end = limit
}

chunks[idx] = strings.Join(chars[offset:end], "")
chunks[idx] = string(chars[offset:end])
offset += length
idx++
}
Expand All @@ -188,7 +214,7 @@ func Chunk(str string, length int) []string {

// Truncates the given string to the given length (including the ending `...`).
func Truncate(str string, length int) string {
chars := strings.Split(str, "")
chars := []rune(str)
limit := len(chars)

if length <= 0 {
Expand All @@ -198,7 +224,7 @@ func Truncate(str string, length int) string {
} else {
length -= 3

return strings.Join(chars[0:length], "") + "..."
return string(chars[0:length]) + "..."
}
}

Expand Down
52 changes: 38 additions & 14 deletions stringx/stringx.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"math/rand"
"regexp"
"strings"

"github.com/ayonli/goext/slicex"
)

var wordRegex = regexp.MustCompile(`\w+`)
Expand Down Expand Up @@ -44,41 +46,63 @@ func EndsWith(str string, sub string) bool {
// Pads the given string with another string (multiple times, if needed) until the resulting string
// reaches the final length. The padding is applied from the start of the string.
func PadStart(str string, finalLength int, padStr string) string {
leftLength := finalLength - len(str)
padLength := finalLength - len(str)

if leftLength <= 0 {
if padLength <= 0 {
return str
}

if len(padStr) > leftLength {
padStr = padStr[0:leftLength]
padChars := []byte(padStr)

if len(padChars) > padLength {
padChars = slicex.Slice(padChars, 0, padLength)
}

for len(str) < finalLength {
str = padStr + str
padCharsLimit := len(padChars) - 1
startChars := make([]byte, padLength)

for i, j := 0, 0; i < padLength; i++ {
startChars[i] = padChars[j]

if j < padCharsLimit {
j++
} else {
j = 0
}
}

return str
return string(startChars) + str
}

// Pads the given string with another string (multiple times, if needed) until the resulting string
// reaches the final length. The padding is applied from the end of the string.
func PadEnd(str string, finalLength int, padStr string) string {
leftLength := finalLength - len(str)
padLength := finalLength - len(str)

if leftLength <= 0 {
if padLength <= 0 {
return str
}

if len(padStr) > leftLength {
padStr = padStr[0:leftLength]
padChars := []byte(padStr)

if len(padChars) > padLength {
padChars = slicex.Slice(padChars, 0, padLength)
}

for len(str) < finalLength {
str += padStr
padCharsLimit := len(padChars) - 1
endChars := make([]byte, padLength)

for i, j := 0, 0; i < padLength; i++ {
endChars[i] = padChars[j]

if j < padCharsLimit {
j++
} else {
j = 0
}
}

return str
return str + string(endChars)
}

// Capitalizes the given string, if `all` is true, all words are capitalized, otherwise only the
Expand Down

0 comments on commit 76359cb

Please sign in to comment.