Android Question Split string - wierd behaviour (at least for me)

mmanso

Active Member
Licensed User
Longtime User
Hi all,

I've used several programming languages in the the past and ususally, when I want to split a string by a certain character, I do something like:

Perl:
my $string = "one#two#three##";
my @array = split /#/, $string;

print $array[0]; # one
print $array[1]; # two
print $array[2]; # three
print $array[3]; # ""
print $array[4]; # ""

I suppose in every languages I've did something like this, the "concept" is the same...

Now, in B4X, I'm trying to achieve this, without success... What I've tryed:

B4X:
    Dim mystring As String = "one#two#three##"
    Dim mylist As List
    mylist.Initialize
  
    For Each mystrings As String In Regex.split("#", mystring)
        mylist.Add(mystrings)
    Next

This snippet, give me a list of three elements (not 5).

I've also trying this, from StringFunctions2:

B4X:
    Dim mystring As String = "one#two#three##"   
    mylist = sf.Split(mystring, "#")

Also, getting a list of three elements

Is there any way to have the expected result (at least for me) of a list of 5 elements (behing the last two, empty string).

Thanks.

ps - I'm posting in the Android forum section because I don't really know where I should post this doubt of mine.
 

mmanso

Active Member
Licensed User
Longtime User
What I've posted, it's just an example... you can't predict if the last two fields will be empty or not to make the Replace you just suggested.
 
Upvote 0

BigBoss123

Member
Licensed User
Longtime User
I have used the following way to spilt a string

B4X:
Private Sub btnSearch_Click
    Dim pos, pos1, pos2 As String
    Dim bar1 As Int
    Dim ware1 As String
    Dim date1 As String
    Dim corr1 As Double
    Dim rs As DBResult
    Dim id As String = cmbox.SelectedItem
    
    Dim Parameters() As String = Array As String(id)
    Wait For(B4XPages.MainPage.jRDC.GetRecord("getproductscust", Parameters)) Complete (Answer As Map)
    If Answer.Get("Success") Then
            
        rs = Answer.Get("Data")
        x = 0
        For Each row() As Object In rs.Rows
            bar1 = (row(rs.Columns.Get("barcode")))   
            date1 = (DateTime.Date(row(rs.Columns.Get("date"))))
            corr1 = (row(rs.Columns.Get("currentbal")))
            If rs.Columns.Get("warehouse") > -1 Then
                ware1 = (row(rs.Columns.Get("warehouse")))
                pos = ware1.SubString2(0,1)
                pos1 = ware1.SubString2(1,3)
                pos2 = ware1.SubString2(3,4)

Using SubString works for me.
 
Upvote 0

Sandman

Expert
Licensed User
Longtime User
There's two different things happening here.
  1. Trailing items from a regex.split are ignored
  2. Empty strings aren't logged
I imagine both of these are bugs and probably should be reported as such.

B4X:
    Dim i As Int
    Dim input As String = "##one#two##three##"
    Dim output() As String = Regex.Split("#", input)
    For Each item As String In output
        Log("----- Iteration " & i & " -----")
        Log(item)
        Log("item: " & item)
        i = i + 1
    Next

Result in the log:
B4X:
----- Iteration 0 -----
item:
----- Iteration 1 -----
item:
----- Iteration 2 -----
one
item: one
----- Iteration 3 -----
two
item: two
----- Iteration 4 -----
item:
----- Iteration 5 -----
three
item: three
 
Upvote 0

Quandalle

Member
Licensed User
java split method ignore trailing empty string. In java there is an other method with an additional parameter "limit" that preserves, but this limit parameter is not exposed in B4x
There are several workarounds (inline java to access the limit parameter, code the split function yourself, more advanced regex, ...)

a simple workaround could be in this case something like :
B4X:
    Dim mystring As String = "one#two#three##"
    Dim mylist As List  = Regex.Split("#",mystring.Replace ("#","# "))
    Log(mylist)

then you just have to trim if necessary to remove the space at the top of each element of the list
 
Upvote 0

mmanso

Active Member
Licensed User
Longtime User
Just for reference, this suits my needs:

B4X:
Public Sub StrSplit(text As String, delimiter As String) As List
    Dim mylist As List  = Regex.Split(delimiter, text.Replace(delimiter, delimiter & " "))

    Dim mylistfinal As List
    mylistfinal.Initialize

    For Each elem As String In mylist
        mylistfinal.Add(elem.Trim)
    Next

    Return mylistfinal
End Sub
 
Upvote 0

Quandalle

Member
Licensed User
below a solution using the limit parameter of java not accessible from b4x

B4X:
Sub inline As JavaObject
    Return Me
End Sub

#if java
public static String[] split2(String s, String sep){
   return s.split(sep, Integer.MAX_VALUE);
}
#end if

Sub AppStart (Args() As String)
    ' result in an array of string
    Dim d() As String = inline.RunMethod("split2",Array As String("one#two#three##","#"))
    For i= 0 To d.Length-1
        Log( i &  ":" & d(i))
    Next 
  
    ' result in a list
    Dim li As List
    li.Initialize2(d)
    log(li)
End Sub
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I would have used CSVParser for this case:
B4X:
Dim parser As CSVParser
parser.Initialize
Dim items() As String = parser.Parse("one#two#three##","#", False).Get(0)
For Each it As String In items
    Log("item: " & it)
Next

 
Upvote 0

Quandalle

Member
Licensed User
I would have used CSVParser for this case:


In most cases, the CSVParser will give the same result as a split ( including of course trailing empty strings ).

But the semantics of a CSV is slightly different than a simple split, because the CSV introduces a meaning to the QUOTE caracter

For example if the string to split is : ONE#T "O#THREE
(the W of TWO is now a QUOTE) the result will be different between csvParser and a simple split
The split will give 3 fields : ONE, T "O, THREE
The CSVParser will give only one field : ONE
 
Upvote 0
Top