Android Question Order String

imgsimonebiliato

Well-Known Member
Licensed User
Longtime User
Hello,
please I need some help ordering a string.

This string: C1, P5, S3, C5, S9, C3, S1, P1
To this: P1, P3, S3, S9, C1, C3, C5

So how to order? The strings with letter "P" must be the first, then "S" and "C" finally
 
You'll need to implement an IsLessThan method that takes two parameters (two of your Strings) and returns a Boolean. Then, once you have that, you can use any generic sorting algorithm like a bubble sort.

You'll probably want something along these lines:
Code:
'Returns True if if a<b
Sub IsLessThan(a As String, b As String) as Boolean
     Dim aPrefix as String = a.GetCharAt(0)
     Dim aNum as Int = a.GetCharAt(1)
     Dim bPrefix as String = b.GetCharAt(0)
     Dim bNum as Int = b.GetCharAt(1)
     If aPrefix=="P" Then
          If bPrefix<>"P" Then 
             Return True
          Else
             Return aNum<bNum
     Else
          If aPrefix==bPrefix Then Return aNum<bNum
          Return aPrefix=="S"
     End If
End Sub

This code isn't tested so make sure you test it to see that it does what you want.

Now you can implement any generic sorting algorithm. A bubble sort is simple (though not the fastest): https://en.wikipedia.org/wiki/Bubble_sort
 
Upvote 0
Here is another method. Just replace "P" with "A", and "S" with "B". Then split the string into a list to be sorted, then recombine into a single string, Replace the original letters.
Code:
    Dim s As String = "C1, P5, S3, C5, S9, C3, S1, P1"
    Dim a As List
    a.Initialize
    s = s.Replace("P","A")
    s = s.Replace("S","B")
    a.AddAll(Regex.split(", ",s))
    a.Sort(True)
    s = ""
    For Each c As String In a
        s = s & c & ", "
    Next
    s = s.SubString2(0,s.Length - 2)
    s = s.Replace("A", "P")
    s = s.Replace("B", "S")
    Log(s)
 
Upvote 0
Here is another method. Just replace "P" with "A", and "S" with "B". Then split the string into a list to be sorted, then recombine into a single string, Replace the original letters.
Code:
    Dim s As String = "C1, P5, S3, C5, S9, C3, S1, P1"
    Dim a As List
    a.Initialize
    s = s.Replace("P","A")
    s = s.Replace("S","B")
    a.AddAll(Regex.split(", ",s))
    a.Sort(True)
    s = ""
    For Each c As String In a
        s = s & c & ", "
    Next
    s = s.SubString2(0,s.Length - 2)
    s = s.Replace("A", "P")
    s = s.Replace("B", "S")
    Log(s)

Thank you, this is useful.

But If I get : "C1, P50, S3, C5, S10, C3, S1, P1"
The result is "P1, P50, S1, S10, S3, C1, C3, C5"

If you see S10 if before S3 and must be contrary.
How do i solve?
 
Upvote 0
Another way is to create three separate Lists, a PList, an SList and a CList, filled accordingly. Strip the letters from each element in the List so you just have numbers, remaining (make sure they are actually of an Int type, not just a String representation of an integer). Then sort each list. Then you can put the sequence back together, with the PList first, then the SList, then the CList.
 
Upvote 0
Another way is to create three separate Lists, a PList, an SList and a CList, filled accordingly. Strip the letters from each element in the List so you just have numbers, remaining (make sure they are actually of an Int type, not just a String representation of an integer). Then sort each list. Then you can put the sequence back together, with the PList first, then the SList, then the CList.

I tried to do that but without success.. If you can help me.
Also I prefer the method of @James Chamblin , but there is the other error

:(:(:(:(
 
Upvote 0
Yes! I solved!!

Simply replace the number 10 with Z, and then the sort work!
I know that it is a silly solution, but for my little program, it works fine..

Thank all!
 
Upvote 0
If you know beforehand that the number following the leading letter is made up of "x" digits at maximum, just "normalize" the numeric part of each element pre-pending enough 0s.
So P1 becomes P01 when you know that a letter is followed by at most 2 digits, or that same P1 becomes P001 if the digits are three.
You can generalize the concept with a discovering function (to discover the number of digits) and an eventual clean-up function to stripe the extra zeros when done.

udg
 
Upvote 0
numbers in strings are compared differently than in ints. My example worked because the numbers are all single digits. If you don't mind having leading 0's on all your numbers, then you could use a string like "C01, P50, S03, C05, S10, C03, S01, P01" and it will work. If you can't do that, then you will need to treat numbers and letters separately, similar to what Roycefer has done.

Modified Roycefer's IsLessThan() Sub and added a bubble sort here.
Code:
Sub ProcessString
    Dim s As String = "C1, P50, S3, C5, S10, C3, S1, P1"
    Dim a As List
    a.Initialize

    a.AddAll(Regex.split(", ",s))
    SortComponents(a)
    s = ""
    For Each c As String In a
        s = s & c & ", "
    Next
    s = s.SubString2(0,s.Length - 2)

    Log(s)   
End Sub

Sub SortComponents(l As List)
    Dim index As Int = 0
    Dim Top As Int
    For Top = l.Size - 2 To 0 Step - 1
        For index = 0 To Top
            If IsLessThan(l.Get(index+1),l.Get(index)) Then
                Dim temp As String = l.Get(index)
                l.Set(index,l.Get(index+1))
                l.Set(index+1,temp)
               
               
            End If
        Next
    Next
End Sub

Sub IsLessThan(a As String, b As String) As Boolean
     Dim aPrefix As String = a.charat(0)
     Dim aNum As Int = a.SubString(1)
     Dim bPrefix As String = b.CharAt(0)
     Dim bNum As Int = b.SubString(1)
    If aPrefix = bPrefix Then Return aNum<bNum
    Select aPrefix
        Case "P"
            Return True
        Case "S"
            Select bPrefix
                Case "P"
                    Return False
                Case Else
                    Return True
            End Select
        Case Else
            Return False
                   
    End Select
End Sub
 
Upvote 0
Hello,
please I need some help ordering a string.

This string: C1, P5, S3, C5, S9, C3, S1, P1
To this: P1, P3, S3, S9, C1, C3, C5

So how to order? The strings with letter "P" must be the first, then "S" and "C" finally
Hello hello!

Here's my approach [fixed]:

1. Add this function to your code.
Code:
Sub SetCustomOrder(originalString As String, customOrder As String, ascending As Boolean) As String 
    Dim tempString, finalString   As String
    Dim tempList(2)               As List
    For co = 0 To (customOrder.Length - 1)
        tempList(0).Initialize
        tempList(1).Initialize
        For os = 0 To (originalString.Length - 1)
            If originalString.CharAt(os) = customOrder.CharAt(co) Then
                tempList(0).Add(originalString.CharAt(os))
                For n = Min(os + 1, (originalString.Length - 1)) To (originalString.Length - 1)
                    If Asc(originalString.CharAt(n)) >= Asc("0") And Asc(originalString.CharAt(n)) <= Asc("9") Then
                        tempString = tempString & originalString.CharAt(n)
                    Else
                        Exit
                    End If
                Next
                Dim num = tempString As Long
                tempList(1).Add(num)
                tempString = ""
            End If
        Next
        tempList(1).Sort(ascending)
        For l = 0 To (tempList(0).Size - 1)
            finalString = finalString & tempList(0).Get(l) & tempList(1).Get(l) & ", "
        Next
    Next
    Return finalString.SubString2(0, Max(0, finalString.Length - 2))
End Sub


2. Use it like this:
Code:
myString = SetCustomOrder(myString, "PSC", True)

B4J Screenshot:
Untitled.png
 
Last edited:
Upvote 0
@wonder:
Your function returns for this string: C1, P50, S3, C5, S10, C3, S1, P1
a new string like this: €P1, €P50, S1, S10, S3, ‚C1, ‚C3, ‚C5
But I think the old boy wants S3 to be ahead of S10.
 
Upvote 0
@wonder:
Your function returns for this string: C1, P50, S3, C5, S10, C3, S1, P1
a new string like this: €P1, €P50, S1, S10, S3, ‚C1, ‚C3, ‚C5
But I think the old boy wants S3 to be ahead of S10.
I see, I'll try to fix it tomorrow. Thanks for noticing! :)
 
Upvote 0
This is the code for my second solution:
Code:
Dim input as String = "S3, C1024, etc....."
Dim PList, SList, CList as List
PList.Initialize: SList.Initialize: CList.Initialize
Dim stArr() as String = Regex.Split(",", input)
For j = 0 to stArr.Length-1
   Dim prefix as String = stArr(j).GetCharAt(0)
   Dim num as Int = stArr(j).Trim.SubString(1)
   Select prefix
      Case "P"
         PList.Add(num)
      Case "S"
         SList.Add(num)
      Case "C"
         CList.Add(num)
   End Select
Next

PList.Sort(True)
CList.Sort(True)
SList.Sort(True)

Dim result as StringBuilder
result.Initialize
For j = 0 to PList.Size-1
   result.Append("P").Append(PList.Get(j)).Append(" ,")
Next
For j = 0 to SList.Size-1
   result.Append("S").Append(SList.Get(j)).Append(" ,")
Next
For j = 0 to CList.Size-1
   result.Append("C").Append(CList.Get(j))
      If j<CList.Size-1 Then result.Append(" ,")
Next

'print out the answer:
Log(result.ToString)

Again, this is untested.
 
Upvote 0
@Roycefer
Your solution will work if you add the below line under the Dim Input line:
Code:
input=input.Replace(" ","")
And if you replace this line:
Code:
Dim prefix as String = stArr(j).GetCharAt(0)
with:
Code:
Dim prefix as String = stArr(j).CharAt(0)
Not bad for someone who has not had a chance to test it. Where have you been hiding all these years. You are a powerhouse.
 
Last edited:
Upvote 0
Ha, thanks. I knew there had to be some errors in there. That's what you get when you enter code directly into the forum's text editor. Coding without syntax highlighting, auto-complete and error catching is like driving without a seat belt, airbag and windshield. Erel should implement the full IDE in the forum's text editor.
 
Upvote 0
I'm either not getting the point or all given example are too complex to how I interpret it.

here's how I interpret it

Code:
Dim data As String = "C1, P5, S3, C5, S9, C3, S1, P1"
Dim temp,output,item,items() As String
Dim l As List
l.Initialize
items=Regex.Split(", ",data)
For x=0 To items.Length-1
If items(x).StartsWith("P") Then l.Add(1 & items(x))
If items(x).StartsWith("S") Then l.Add(2 & items(x))
If items(x).StartsWith("C") Then l.Add(3 & items(x))
Next
l.Sort(True)
For x=0 To l.Size-1
item=l.Get(x)
output=output & item.SubString(1)
If x<l.Size-1 Then output=output&", "
Next
Log(output)

which outputs

** Activity (main) Create, isFirst = true **
P1, P5, S1, S3, S9, C1, C3, C5
** Activity (main) Resume **
 
Upvote 0
ok, ignore my post I just read that he want nummerical sort for numbers with multiple digits aswell
 
Upvote 0
this works for any numerical data aswell

Code:
Sub Globals
Type mydata (sorttext As String,text As String)
End Sub

Sub Activity_Create(FirstTime As Boolean)
Dim data As String = "C1, P5, S3, C5, S9, C3, S1, P1, S10, S939"
Dim output,items(),prefix,num As String
Dim l As List
l.Initialize
items=Regex.Split(", ",data)
For x=0 To items.Length-1
Dim md As mydata
md.Initialize
num=("000000"&items(x).SubString(1))
If items(x).StartsWith("P") Then prefix="1"
If items(x).StartsWith("S") Then prefix="2"
If items(x).StartsWith("C") Then prefix="3"
md.sorttext=prefix &"-"&  num.SubString(num.Length-5)
md.text=items(x)
l.Add(md)
Next
l.SortType("sorttext",True)
For x=0 To l.Size-1
md=l.Get(x)
output=output & md.text
If x<l.Size-1 Then output=output&", "
Next
Log(output)

output: P1, P5, S1, S3, S9, S10, S939, C1, C3, C5

the trick is to create a sorting value so the data is stored as (prefix order, value order)

2-00010
1-00001
1-00005
2-00001
2-00003
2-00009
2-00010
2-00939
...

which makes the sort work correct
 
Last edited:
Upvote 0
Hi sorex,
I see you solved the problem in a way similar to what I suggested in post #8 above, but smartly avoided the clean-up function using your mydata data structure.
Well done.
This reminds me that too many years spent programming on scarce-RAM devices (64-128KB) lead to think more in terms of using as few resources as possible than on CPU cycles and time to complete. Not a winning point of view these days of monstrous GB RAM devices! eheh

udg
 
Upvote 0
Back
Top