mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin: add rsplit
functions (#17577)
This commit is contained in:
parent
ee4150f213
commit
9fa49da9d5
@ -757,6 +757,36 @@ pub fn (s string) split_any(delim string) []string {
|
||||
return res
|
||||
}
|
||||
|
||||
// rsplit_any splits the string to an array by any of the `delim` chars in reverse order.
|
||||
// Example: "first row\nsecond row".rsplit_any(" \n") == ['row', 'second', 'row', 'first']
|
||||
// Split a string using the chars in the delimiter string as delimiters chars.
|
||||
// If the delimiter string is empty then `.rsplit()` is used.
|
||||
[direct_array_access]
|
||||
pub fn (s string) rsplit_any(delim string) []string {
|
||||
mut res := []string{}
|
||||
mut i := s.len - 1
|
||||
if s.len > 0 {
|
||||
if delim.len <= 0 {
|
||||
return s.rsplit('')
|
||||
}
|
||||
mut rbound := s.len
|
||||
for i >= 0 {
|
||||
for delim_ch in delim {
|
||||
if s[i] == delim_ch {
|
||||
res << s[i + 1..rbound]
|
||||
rbound = i
|
||||
break
|
||||
}
|
||||
}
|
||||
i--
|
||||
}
|
||||
if rbound > 0 {
|
||||
res << s[..rbound]
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// split splits the string to an array by `delim`.
|
||||
// Example: assert 'A B C'.split(' ') == ['A','B','C']
|
||||
// If `delim` is empty the string is split by it's characters.
|
||||
@ -765,6 +795,52 @@ pub fn (s string) split(delim string) []string {
|
||||
return s.split_nth(delim, 0)
|
||||
}
|
||||
|
||||
// rsplit splits the string to an array by `delim` in reverse order.
|
||||
// Example: assert 'A B C'.rsplit(' ') == ['C','B','A']
|
||||
// If `delim` is empty the string is split by it's characters.
|
||||
// Example: assert 'DEF'.rsplit('') == ['F','E','D']
|
||||
pub fn (s string) rsplit(delim string) []string {
|
||||
return s.rsplit_nth(delim, 0)
|
||||
}
|
||||
|
||||
// split_once devides string into pair of string by `delim`.
|
||||
// Example:
|
||||
// ```v
|
||||
// path, ext := 'file.ts.dts'.splice_once('.')?
|
||||
// assert path == 'file'
|
||||
// assert ext == 'ts.dts'
|
||||
// ```
|
||||
// Note that rsplit_once returns splitted string string as first part of pair,
|
||||
// and returns remaining as second part of pair.
|
||||
pub fn (s string) split_once(delim string) ?(string, string) {
|
||||
result := s.split_nth(delim, 2)
|
||||
|
||||
if result.len != 2 {
|
||||
return none
|
||||
}
|
||||
|
||||
return result[0], result[1]
|
||||
}
|
||||
|
||||
// rsplit_once devides string into pair of string by `delim`.
|
||||
// Example:
|
||||
// ```v
|
||||
// path, ext := 'file.ts.dts'.splice_once('.')?
|
||||
// assert path == 'file.ts'
|
||||
// assert ext == 'dts'
|
||||
// ```
|
||||
// Note that rsplit_once returns remaining string as first part of pair,
|
||||
// and returns splitted string as second part of pair.
|
||||
pub fn (s string) rsplit_once(delim string) ?(string, string) {
|
||||
result := s.rsplit_nth(delim, 2)
|
||||
|
||||
if result.len != 2 {
|
||||
return none
|
||||
}
|
||||
|
||||
return result[1], result[0]
|
||||
}
|
||||
|
||||
// split_nth splits the string based on the passed `delim` substring.
|
||||
// It returns the first Nth parts. When N=0, return all the splits.
|
||||
// The last returned element has the remainder of the string, even if
|
||||
@ -839,6 +915,74 @@ pub fn (s string) split_nth(delim string, nth int) []string {
|
||||
}
|
||||
}
|
||||
|
||||
// rsplit_nth splits the string based on the passed `delim` substring in revese order.
|
||||
// It returns the first Nth parts. When N=0, return all the splits.
|
||||
// The last returned element has the remainder of the string, even if
|
||||
// the remainder contains more `delim` substrings.
|
||||
[direct_array_access]
|
||||
pub fn (s string) rsplit_nth(delim string, nth int) []string {
|
||||
mut res := []string{}
|
||||
mut i := s.len - 1
|
||||
|
||||
match delim.len {
|
||||
0 {
|
||||
for i >= 0 {
|
||||
if nth > 0 && res.len == nth - 1 {
|
||||
res << s[..i]
|
||||
break
|
||||
}
|
||||
res << s[i].ascii_str()
|
||||
i--
|
||||
}
|
||||
return res
|
||||
}
|
||||
1 {
|
||||
mut rbound := s.len
|
||||
delim_byte := delim[0]
|
||||
|
||||
for i >= 0 {
|
||||
if s[i] == delim_byte {
|
||||
if nth > 0 && res.len == nth - 1 {
|
||||
break
|
||||
}
|
||||
res << s[i + 1..rbound]
|
||||
rbound = i
|
||||
i--
|
||||
} else {
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
if nth < 1 || res.len < nth {
|
||||
res << s[..rbound]
|
||||
}
|
||||
return res
|
||||
}
|
||||
else {
|
||||
mut rbound := s.len
|
||||
|
||||
for i >= 0 {
|
||||
is_delim := i - delim.len >= 0 && s[i - delim.len..i] == delim
|
||||
if is_delim {
|
||||
if nth > 0 && res.len == nth - 1 {
|
||||
break
|
||||
}
|
||||
res << s[i..rbound]
|
||||
rbound = i - delim.len
|
||||
i -= delim.len
|
||||
} else {
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
if nth < 1 || res.len < nth {
|
||||
res << s[..rbound]
|
||||
}
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// split_into_lines splits the string by newline characters.
|
||||
// newlines are stripped.
|
||||
// `\r` (MacOS), `\n` (POSIX), and `\r\n` (WinOS) line endings are all supported (including mixed line endings).
|
||||
|
@ -188,6 +188,37 @@ fn test_split_nth() {
|
||||
assert e.split_nth(',', 3).len == 3
|
||||
}
|
||||
|
||||
fn test_rsplit_nth() {
|
||||
a := '1,2,3'
|
||||
assert a.rsplit(',').len == 3
|
||||
assert a.rsplit_nth(',', -1).len == 3
|
||||
assert a.rsplit_nth(',', 0).len == 3
|
||||
assert a.rsplit_nth(',', 1).len == 1
|
||||
assert a.rsplit_nth(',', 2).len == 2
|
||||
assert a.rsplit_nth(',', 10).len == 3
|
||||
b := '1::2::3'
|
||||
assert b.rsplit('::').len == 3
|
||||
assert b.rsplit_nth('::', -1).len == 3
|
||||
assert b.rsplit_nth('::', 0).len == 3
|
||||
assert b.rsplit_nth('::', 1).len == 1
|
||||
assert b.rsplit_nth('::', 2).len == 2
|
||||
assert b.rsplit_nth('::', 10).len == 3
|
||||
c := 'ABCDEF'
|
||||
assert c.rsplit('').len == 6
|
||||
assert c.rsplit_nth('', 3).len == 3
|
||||
assert c.rsplit_nth('BC', -1).len == 2
|
||||
d := ','
|
||||
assert d.rsplit(',').len == 2
|
||||
assert d.rsplit_nth('', 3).len == 1
|
||||
assert d.rsplit_nth(',', -1).len == 2
|
||||
assert d.rsplit_nth(',', 3).len == 2
|
||||
e := ',,,0,,,,,a,,b,'
|
||||
assert e.rsplit(',,').len == 5
|
||||
assert e.rsplit_nth(',,', 3).len == 3
|
||||
assert e.rsplit_nth(',', -1).len == 12
|
||||
assert e.rsplit_nth(',', 3).len == 3
|
||||
}
|
||||
|
||||
fn test_split_nth_values() {
|
||||
line := 'CMD=eprintln(phase=1)'
|
||||
|
||||
@ -219,6 +250,37 @@ fn test_split_nth_values() {
|
||||
assert a4[2] == '1)'
|
||||
}
|
||||
|
||||
fn test_rsplit_nth_values() {
|
||||
line := 'CMD=eprintln(phase=1)'
|
||||
|
||||
a0 := line.rsplit_nth('=', 0)
|
||||
assert a0.len == 3
|
||||
assert a0[0] == '1)'
|
||||
assert a0[1] == 'eprintln(phase'
|
||||
assert a0[2] == 'CMD'
|
||||
|
||||
a1 := line.rsplit_nth('=', 1)
|
||||
assert a1.len == 1
|
||||
assert a1[0] == 'CMD=eprintln(phase=1)'
|
||||
|
||||
a2 := line.rsplit_nth('=', 2)
|
||||
assert a2.len == 2
|
||||
assert a2[0] == '1)'
|
||||
assert a2[1] == 'CMD=eprintln(phase'
|
||||
|
||||
a3 := line.rsplit_nth('=', 3)
|
||||
assert a3.len == 3
|
||||
assert a0[0] == '1)'
|
||||
assert a0[1] == 'eprintln(phase'
|
||||
assert a0[2] == 'CMD'
|
||||
|
||||
a4 := line.rsplit_nth('=', 4)
|
||||
assert a4.len == 3
|
||||
assert a0[0] == '1)'
|
||||
assert a0[1] == 'eprintln(phase'
|
||||
assert a0[2] == 'CMD'
|
||||
}
|
||||
|
||||
fn test_split() {
|
||||
mut s := 'volt/twitch.v:34'
|
||||
mut vals := s.split(':')
|
||||
@ -265,6 +327,52 @@ fn test_split() {
|
||||
assert vals[1] == ''
|
||||
}
|
||||
|
||||
fn test_rsplit() {
|
||||
mut s := 'volt/twitch.v:34'
|
||||
mut vals := s.rsplit(':')
|
||||
assert vals.len == 2
|
||||
assert vals[0] == '34'
|
||||
assert vals[1] == 'volt/twitch.v'
|
||||
// /////////
|
||||
s = '2018-01-01z13:01:02'
|
||||
vals = s.rsplit('z')
|
||||
assert vals.len == 2
|
||||
assert vals[0] == '13:01:02'
|
||||
assert vals[1] == '2018-01-01'
|
||||
// //////////
|
||||
s = '4627a862c3dec29fb3182a06b8965e0025759e18___1530207969___blue'
|
||||
vals = s.rsplit('___')
|
||||
assert vals.len == 3
|
||||
assert vals[0] == 'blue'
|
||||
assert vals[1] == '1530207969'
|
||||
assert vals[2] == '4627a862c3dec29fb3182a06b8965e0025759e18'
|
||||
// /////////
|
||||
s = 'lalala'
|
||||
vals = s.rsplit('a')
|
||||
assert vals.len == 4
|
||||
assert vals[0] == ''
|
||||
assert vals[1] == 'l'
|
||||
assert vals[2] == 'l'
|
||||
assert vals[3] == 'l'
|
||||
// /////////
|
||||
s = 'awesome'
|
||||
a := s.rsplit('')
|
||||
assert a.len == 7
|
||||
assert a[0] == 'e'
|
||||
assert a[1] == 'm'
|
||||
assert a[2] == 'o'
|
||||
assert a[3] == 's'
|
||||
assert a[4] == 'e'
|
||||
assert a[5] == 'w'
|
||||
assert a[6] == 'a'
|
||||
// /////////
|
||||
s = 'wavy turquoise bags'
|
||||
vals = s.rsplit('wavy ')
|
||||
assert vals.len == 2
|
||||
assert vals[0] == 'turquoise bags'
|
||||
assert vals[1] == ''
|
||||
}
|
||||
|
||||
fn test_split_any() {
|
||||
assert 'ABC'.split_any('') == ['A', 'B', 'C']
|
||||
assert ''.split_any(' ') == []
|
||||
@ -276,6 +384,41 @@ fn test_split_any() {
|
||||
assert 'first row\nsecond row'.split_any(' \n') == ['first', 'row', 'second', 'row']
|
||||
}
|
||||
|
||||
fn test_rsplit_any() {
|
||||
assert 'ABC'.rsplit_any('') == ['C', 'B', 'A']
|
||||
assert ''.rsplit_any(' ') == []
|
||||
assert ' '.rsplit_any(' ') == ['']
|
||||
assert ' '.rsplit_any(' ') == ['', '']
|
||||
assert ' Ciao come stai?'.rsplit_any(' ') == ['stai?', 'come', 'Ciao']
|
||||
assert ' Ciao+come*stai?'.rsplit_any('+*') == ['stai?', 'come', ' Ciao']
|
||||
assert ' Ciao+come*stai?'.rsplit_any('+* ') == ['stai?', 'come', 'Ciao']
|
||||
assert 'first row\nsecond row'.rsplit_any(' \n') == ['row', 'second', 'row', 'first']
|
||||
}
|
||||
|
||||
fn test_split_once() ? {
|
||||
path1, ext1 := 'home/dir/lang.zip'.split_once('.')?
|
||||
assert path1 == 'home/dir/lang'
|
||||
assert ext1 == 'zip'
|
||||
path2, ext2 := 'home/dir/lang.ts.dts'.split_once('.')?
|
||||
assert path2 == 'home/dir/lang'
|
||||
assert ext2 == 'ts.dts'
|
||||
path3, ext3 := 'home/dir'.split_once('.') or { '', '' }
|
||||
assert path3 == ''
|
||||
assert ext3 == ''
|
||||
}
|
||||
|
||||
fn test_rsplit_once() ? {
|
||||
path1, ext1 := 'home/dir/lang.zip'.rsplit_once('.')?
|
||||
assert path1 == 'home/dir/lang'
|
||||
assert ext1 == 'zip'
|
||||
path2, ext2 := 'home/dir/lang.ts.dts'.rsplit_once('.')?
|
||||
assert path2 == 'home/dir/lang.ts'
|
||||
assert ext2 == 'dts'
|
||||
path3, ext3 := 'home/dir'.rsplit_once('.') or { '', '' }
|
||||
assert path3 == ''
|
||||
assert ext3 == ''
|
||||
}
|
||||
|
||||
fn test_trim_space() {
|
||||
a := ' a '
|
||||
assert a.trim_space() == 'a'
|
||||
|
Loading…
Reference in New Issue
Block a user