Array Length is set by Regex.Split

MichaelAust

Member
Licensed User
Longtime User
With the following code
B4X:
Sub Activity_Create(FirstTime As Boolean)
   Dim TestArray(7) As String
   TestArray=Regex.Split(",","1,2,3,4,5,6,7")
   Msgbox(TestArray.Length,"")
   TestArray=Regex.Split(",","1,2,3,4,5,6,")
   Msgbox(TestArray.Length,"")
End Sub
The array length is 7 the first time, but 6 the second time. This causes an out of range exception if I try to read TestArray(6). I Thought that using
B4X:
   Dim TestArray(7) As String
would mean the array always had seven elements. Do I have to test the array length before reading or is there a way around this ?

If the string is "1,2,3,4,5,," then TestArray.Length is only 5.

I think that Regex.Split() should return a seven element array even if the string is ",,,,,," (Length is 1 for this) otherwise a lot of what if code will be required depending on the input data.
 
Last edited:

Mahares

Expert
Licensed User
Longtime User
If you replace this line :
B4X:
TestArray=Regex.Split(",","1,2,3,4,5,6,")
with this line, it will show you 7. (2 single quotes)
B4X:
TestArray=Regex.Split(",","1,2,3,4,5,6,''")
 
Upvote 0

MichaelAust

Member
Licensed User
Longtime User
If you replace this line :
B4X:
TestArray=Regex.Split(",","1,2,3,4,5,6,")
with this line, it will show you 7. (2 single quotes)
B4X:
TestArray=Regex.Split(",","1,2,3,4,5,6,''")

I am reading the data from a text file, and it is not practical to change the format of the text file.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Regex.Split returns a new array. The previous one is ignored. (Note that Regex.Split doesn't "know" that you are assigning the result to an array)

You could create a simple sub like:
B4X:
TestArray(PadString(Regex.Split(...), 7))

Sub PadStrings(str() As String, targetLength as Int) As String()
 If str.Length = targetLength Then return str
 Dim res(targetLength) As String
 For i = 0 to targetLength - 1
  if i >= str.Length then res(i) = "" else res(i) = str(i)
 Next
 Return res
End Sub
 
Upvote 0

MichaelAust

Member
Licensed User
Longtime User
Regex.Split returns a new array. The previous one is ignored. (Note that Regex.Split doesn't "know" that you are assigning the result to an array)

You could create a simple sub like:
B4X:
TestArray(PadString(Regex.Split(...), 7))

Sub PadStrings(str() As String, targetLength as Int) As String()
 If str.Length = targetLength Then return str
 Dim res(targetLength) As String
 For i = 0 to targetLength - 1
  if i >= str.Length then res(i) = "" else res(i) = str(i)
 Next
 Return res
End Sub

Thanks for the reply. I have tested 2 methods which both work, the first based on your method

B4X:
Sub SafeSplit(Pattern As String, Text As String) As String()
   ' Same as Regex.Split but returns an array with 1 element per Pattern in Text + 1.
   Dim PatternCt As Int
   Dim Matcher1 As Matcher
   Dim InitArray() As String

   ' Do the initial Split, returning a possibly short array.
   InitArray=Regex.Split(Pattern,Text)

   ' Find the number of Patterns in Text.
   Matcher1 = Regex.Matcher(Pattern, Text)
   Do While Matcher1.Find
      PatternCt=PatternCt+1
   Loop
   
   Dim ResultArray(PatternCt+1) As String ' 1 before the 1st, 1 after the last.
   For i = 0 To PatternCt
      If i >= InitArray.Length Then 
         ResultArray(i) = "" 
      Else
         ResultArray(i) = InitArray(i)
      End If
   Next
   Return ResultArray
End Sub
And the second which is simpler but feels a bit less elegant. (gets called more times and I might forget to call it if I edit the code later)
B4X:
Sub SafeReadArray(ArrayToRead() As String, Index As Int) As String
   ' Check if Index is within ArrayToRead.Length, and return "" if not.
   If Index<ArrayToRead.Length Then
     Return ArrayToRead(Index)
   Else
      Return ""
   End If
End Sub
 
Upvote 0
Top