Skip to content

Commit a8fdaf2

Browse files
committed
Refactor string split functions
1 parent b05df3f commit a8fdaf2

File tree

3 files changed

+63
-21
lines changed

3 files changed

+63
-21
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ go get github.com/tiendc/gofn
130130
**String**
131131
- [RuneLength](#runelength)
132132
- [RandString / RandStringEx](#randstring--randstringex)
133-
- [StringSplitEx](#stringsplitex)
133+
- [StringSplit / StringSplitN](#stringsplit--stringsplitn)
134134
- [StringJoin / StringJoinEx / StringJoinBy](#stringjoin--stringjoinex--stringjoinby)
135135
- [StringLexJoin / StringLexJoinEx](#stringlexjoin--stringlexjoinex)
136136
- [StringWrap / StringUnwrap](#stringwrap--stringunwrap)
@@ -1064,13 +1064,14 @@ RandString(10) // Generates a string of 10 characters fr
10641064
RandStringEx(10, []rune("0123456789")) // Generates a string of 10 characters from the specified ones
10651065
```
10661066

1067-
#### StringSplitEx
1067+
#### StringSplit / StringSplitN
10681068

10691069
Splits a string with handling quotes by ignoring any separator within the quotes.
10701070

10711071
```go
1072-
StringSplitEx("ab cd \"12 34\"", " ", "\"") // "[]string{"ab", "cd", "\"12 34\""}
1073-
StringSplitEx("ab cd {12 34}", " ", "{ }") // "[]string{"ab", "cd", "{12 34}"}
1072+
StringSplit("ab cd \"12 34\"", " ", "\"") // "[]string{"ab", "cd", "\"12 34\""}
1073+
StringSplit("ab cd {12 34}", " ", "{ }") // "[]string{"ab", "cd", "{12 34}"}
1074+
StringSplitN("ab cd {12 34}", " ", "{ }", 2) // "[]string{"ab", "cd {12 34}"}
10741075
```
10751076

10761077
#### StringJoin / StringJoinEx / StringJoinBy

string.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,20 @@ func StringToLower1stLetter(s string) string {
223223
return string(runes)
224224
}
225225

226-
// StringSplitEx splits a string with handling quotes.
226+
// StringSplit splits a string with handling quotes.
227227
// `quote` param can be a single char (`"`, `'`...) if opening and closing tokens are the same,
228228
// or a space-delimited string (`{ }`, `[ ]`, `{{ }}`...) if the tokens are different.
229-
func StringSplitEx(s string, sep, quote string) (res []string) {
229+
func StringSplit(s string, sep, quote string) (res []string) {
230+
return StringSplitN(s, sep, quote, -1)
231+
}
232+
233+
// StringSplitN splits a string with handling quotes.
234+
// `quote` param can be a single char (`"`, `'`...) if opening and closing tokens are the same,
235+
// or a space-delimited string (`{ }`, `[ ]`, `{{ }}`...) if the tokens are different.
236+
func StringSplitN(s string, sep, quote string, n int) (res []string) {
230237
quoteParts := strings.Split(quote, " ")
231-
if s == "" || sep == "" || quote == "" || len(quoteParts) > 2 {
232-
return strings.Split(s, sep)
238+
if s == "" || sep == "" || quote == "" || len(quoteParts) > 2 || n == 0 || n == 1 {
239+
return strings.SplitN(s, sep, n)
233240
}
234241

235242
runes, sepRunes := []rune(s), []rune(sep)
@@ -254,6 +261,10 @@ func StringSplitEx(s string, sep, quote string) (res []string) {
254261
}
255262
if j, match := stringSubMatch(runes, i, sepRunes); match {
256263
res = append(res, string(currPart))
264+
if n > 0 && len(res) == n-1 {
265+
res = append(res, string(runes[j:]))
266+
return res
267+
}
257268
currPart = make([]rune, 0, 10) //nolint:mnd
258269
i = j
259270
continue

string_test.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -204,28 +204,58 @@ func Test_StringToLower1stLetter(t *testing.T) {
204204
assert.Equal(t, "ối", StringToLower1stLetter("Ối"))
205205
}
206206

207-
func Test_StringSplitEx(t *testing.T) {
208-
assert.Equal(t, []string{""}, StringSplitEx("", " ", "\""))
209-
assert.Equal(t, []string{"", ""}, StringSplitEx(" ", " ", "\""))
210-
assert.Equal(t, []string{"", "", ""}, StringSplitEx(",,", ",", "`"))
207+
func Test_StringSplit(t *testing.T) {
208+
// NOTE: most cases are tested by Test_StringSplitN
209+
assert.Equal(t, []string{""}, StringSplit("", " ", "\""))
210+
assert.Equal(t, []string{"", ""}, StringSplit(" ", " ", "\""))
211+
assert.Equal(t, []string{"", "", ""}, StringSplit(",,", ",", "`"))
211212

212-
assert.Equal(t, []string{"abc"}, StringSplitEx("abc", " ", "\""))
213+
assert.Equal(t, []string{"abc"}, StringSplit("abc", " ", "\""))
213214
assert.Equal(t, []string{"", "ab", "", "cd", "12", "", "", "34", ""},
214-
StringSplitEx(" ab cd 12 34 ", " ", "\""))
215+
StringSplit(" ab cd 12 34 ", " ", "\""))
215216
assert.Equal(t, []string{"ab", "xy", "\"12 34 \"56"},
216-
StringSplitEx("ab xy \"12 34 \"56", " ", "\""))
217+
StringSplit("ab xy \"12 34 \"56", " ", "\""))
217218
assert.Equal(t, []string{"ab", "xy", "''12", "34", "'56", ""},
218-
StringSplitEx("ab xy ''12 34 '56 ", " ", "'"))
219+
StringSplit("ab xy ''12 34 '56 ", " ", "'"))
220+
}
221+
222+
func Test_StringSplitN(t *testing.T) {
223+
assert.Equal(t, []string{""}, StringSplitN("", " ", "\"", -1))
224+
assert.Equal(t, []string{"", ""}, StringSplitN(" ", " ", "\"", -1))
225+
assert.Equal(t, []string{"", "", ""}, StringSplitN(",,", ",", "`", -1))
226+
227+
assert.Equal(t, []string{"abc"}, StringSplitN("abc", " ", "\"", -1))
228+
assert.Equal(t, []string{"", "ab", "", "cd", "12", "", "", "34", ""},
229+
StringSplitN(" ab cd 12 34 ", " ", "\"", -1))
230+
assert.Equal(t, []string{"ab", "xy", "\"12 34 \"56"},
231+
StringSplitN("ab xy \"12 34 \"56", " ", "\"", -1))
232+
assert.Equal(t, []string{"ab", "xy", "''12", "34", "'56", ""},
233+
StringSplitN("ab xy ''12 34 '56 ", " ", "'", -1))
219234

220235
assert.Equal(t, []string{"", "ab", "", "cd", "[12 34][ 56 ]", ""},
221-
StringSplitEx(" ab cd [12 34][ 56 ] ", " ", "[ ]"))
236+
StringSplitN(" ab cd [12 34][ 56 ] ", " ", "[ ]", -1))
222237
assert.Equal(t, []string{"", "ab", "", "cd", "[12 34]", "[ 56 ]", ""},
223-
StringSplitEx(" ab cd [12 34] [ 56 ] ", " ", "[ ]"))
238+
StringSplitN(" ab cd [12 34] [ 56 ] ", " ", "[ ]", -1))
224239
assert.Equal(t, []string{"", "ab", "", "cd", "[[12 34]", "56", ""},
225-
StringSplitEx(" ab cd [[12 34] 56 ", " ", "[ ]"))
240+
StringSplitN(" ab cd [[12 34] 56 ", " ", "[ ]", -1))
226241
assert.Equal(t, []string{"", "ab", "", "cd", "[[[12 34]", "56", ""},
227-
StringSplitEx(" ab cd [[[12 34] 56 ", " ", "[ ]"))
242+
StringSplitN(" ab cd [[[12 34] 56 ", " ", "[ ]", -1))
228243

229244
assert.Equal(t, []string{"", "ab", "", "cd", "{{12 34}}", "{56", "78}", ""},
230-
StringSplitEx(" ab cd {{12 34}} {56 78} ", " ", "{{ }}"))
245+
StringSplitN(" ab cd {{12 34}} {56 78} ", " ", "{{ }}", -1))
246+
247+
// When n is not -1
248+
assert.Equal(t, []string(nil), StringSplitN("", " ", "\"", 0))
249+
assert.Equal(t, []string(nil), StringSplitN("abc", " ", "\"", 0))
250+
assert.Equal(t, []string{""}, StringSplitN("", " ", "\"", 1))
251+
assert.Equal(t, []string{"abc"}, StringSplitN("abc", " ", "\"", 1))
252+
253+
assert.Equal(t, []string{"", "ab cd [12 34][ 56 ] "},
254+
StringSplitN(" ab cd [12 34][ 56 ] ", " ", "[ ]", 2))
255+
assert.Equal(t, []string{"ab", " cd [12 34][ 56 ] "},
256+
StringSplitN("ab cd [12 34][ 56 ] ", " ", "[ ]", 2))
257+
assert.Equal(t, []string{"ab", "", "cd [12 34][ 56 ] "},
258+
StringSplitN("ab cd [12 34][ 56 ] ", " ", "[ ]", 3))
259+
assert.Equal(t, []string{"ab", "cd", "[12 34][ 56 ]", ""},
260+
StringSplitN("ab cd [12 34][ 56 ] ", " ", "[ ]", 4))
231261
}

0 commit comments

Comments
 (0)