Get only trailing numbers from a string?
Re: Get only trailing numbers from a string?
@mk-soft
Wow!
At max 20ms, depending on the input string (and the size definition for the fixed string), down to 11 ms (e.g. if limited to 4)^^
Wow!
At max 20ms, depending on the input string (and the size definition for the fixed string), down to 11 ms (e.g. if limited to 4)^^
Re: Get only trailing numbers from a string?
This reduces the time down to around 15 - 20ms for me, sometimes completes in less than that. It's necessary to allocate some memory and pass the pointer to that, as workspace. This reduces the work, since there is no string handling before the final result.s.
EDIT : Simplified without result.s, now reduces the time down to less than 10ms.

Code: Select all
OpenConsole()
EnableExplicit
Procedure.s GetTrailingNumbersFromString8(*StrPtr.Character, *NewStr.Character)
Protected *NewPtr.Character = *NewStr ; Set moving pointer to start of buffer
While *StrPtr\c ; Loop through evaluation until trailing zero
Select *StrPtr\c ; Check non-zero
Case 48 To 57 ; Numeric range 0 to 9
*NewPtr\c = *StrPtr\c ; Move into buffer at *NewPtr
*NewPtr + 2 ; Advance buffer pos.
Default
*NewPtr = *NewStr ; Reset buffer position to start
EndSelect
*StrPtr + 2 ; Next evaluation character
Wend
ProcedureReturn PeekS(*NewStr, (*NewPtr - *NewStr) / 2) ; Return the buffer at fixed calculated no. of chars
EndProcedure
Define.s demoText = "123Caption86"
Define loop.i
Define *NewStr = AllocateMemory(100)
Define t.q = ElapsedMilliseconds()
For loop.i = 1 To 100000
GetTrailingNumbersFromString8(@demoText, *NewStr)
Next
PrintN("Time = " + Str(ElapsedMilliseconds() - t.q) + "ms")
PrintN("Result = " + GetTrailingNumbersFromString8(@demoText, *NewStr))
FreeMemory(*NewStr)
Print("Press <ENTER> : ")
Input()
Last edited by Oso on Sat Dec 30, 2023 4:56 pm, edited 3 times in total.
Re: Get only trailing numbers from a string?
@Oso
Protected result.s{1024} build on stack and not a call string function by ASM
Protected result.s{1024} build on stack and not a call string function by ASM
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Get only trailing numbers from a string?
Optimation 8 with static string buffer
Update 2
Update 2
Code: Select all
;-TOP by mk-soft
CompilerIf #PB_Compiler_Thread
; Static String Buffer Threadsafe
Threaded StringBuffer.s{2048}
CompilerElse
; Static String Buffer
Global StringBuffer.s{2048}
CompilerEndIf
Procedure.s GetNumbersFromString8(*StrPtr.Character)
Protected *result.Character
*result = @StringBuffer
While *StrPtr\c
Select *StrPtr\c
Case '0' To '9'
*result\c = *StrPtr\c
*result + SizeOf(Character)
Default
*result = @StringBuffer
EndSelect
*StrPtr + SizeOf(Character)
Wend
*result\c = #Null
ProcedureReturn StringBuffer
EndProcedure
Define.s demoText = "1234Caption64"
r1.s = GetNumbersFromString8(@demoText)
Debug r1
Last edited by mk-soft on Sat Dec 30, 2023 6:00 pm, edited 2 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Get only trailing numbers from a string?
@mk-soft
Two questions to fully understand what you're doing there:
You're setting the pointer back to the start of the string here?
Let's say the demo string is: 25468test123
Then "25468" is already in the result
The current char is now 't', the pointer is moved back to the start
The loop continues, "123" are captured
The result still contains "12368" because the "68" is a left-over from the leading numbers stored previously
And now:
You're adding the terminating 0 character (in 4th spot after "123") which finally limits our result to only "123"
Correct?
Two questions to fully understand what you're doing there:
Code: Select all
Default
*result = @result
Let's say the demo string is: 25468test123
Then "25468" is already in the result
The current char is now 't', the pointer is moved back to the start
The loop continues, "123" are captured
The result still contains "12368" because the "68" is a left-over from the leading numbers stored previously
And now:
Code: Select all
*result\c = #Null
Correct?
Re: Get only trailing numbers from a string?
Definitely simpler. Is there an advantage to Threaded, over Global? They seem to be the same in performance, difficult to tell exactly, because each test varies. The allocated memory is the fastest, I'm getting < 10ms for that.
Re: Get only trailing numbers from a string?
You got it exactly right.
Can you show your runtime measurement and tell us what method 8 looks like? Once without and once with threadsafe
Can you show your runtime measurement and tell us what method 8 looks like? Once without and once with threadsafe
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Get only trailing numbers from a string?
I have added a second update with compiler option threadsafe.Oso wrote: Sat Dec 30, 2023 5:23 pmDefinitely simpler. Is there an advantage to Threaded, over Global? They seem to be the same in performance, difficult to tell exactly, because each test varies. The allocated memory is the fastest, I'm getting < 10ms for that.
Threaded is only needed if you work with threads. So each thread gets its own string buffer, so that the function is threadsafe
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Get only trailing numbers from a string?
Ok, thanks!
About 13ms for both variants (Create threadsafe executable / or not). No real difference
About 13ms for both variants (Create threadsafe executable / or not). No real difference
Re: Get only trailing numbers from a string?
Thank you 
once again 4 times faster than the other methods. And ThreadSafe
Playing with code with PureBasic is fun

once again 4 times faster than the other methods. And ThreadSafe

Playing with code with PureBasic is fun

My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Get only trailing numbers from a string?
For removing NonWordCharacters we had a similar discussion in summer this year.
As an alternative, here is my final code from this discussing which is very easy to adapt to whatever you want to keep as characters.
It is a full pointer Version which removes the the characters directly from the original String. So it do not touch the String Memory itself
and do not copy the string. This is an advantage if you deal with millions of short strings.
But anyway, the mk-soft version is, as all from mk-soft, very professional and I guess it's be the better solution for your case!
As an alternative, here is my final code from this discussing which is very easy to adapt to whatever you want to keep as characters.
It is a full pointer Version which removes the the characters directly from the original String. So it do not touch the String Memory itself
and do not copy the string. This is an advantage if you deal with millions of short strings.
But anyway, the mk-soft version is, as all from mk-soft, very professional and I guess it's be the better solution for your case!
Code: Select all
Procedure RemoveNonWordChars(*String.Character)
; ============================================================================
; NAME: RemoveNonWordChars
; NAME: Attention! This is a Pointer-Version! Be sure to call it with a
; DESC: correct String-Pointer
; DESC: Removes NonWord Characters from the String
; DESC: The String will be shorter after
; DESC: (question at PB-Forum: https://www.purebasic.fr/english/viewtopic.php?t=82139)
; VAR(*String) : Pointer to String
; RET: -
; ============================================================================
Protected *pWrite.Character = *String
Macro RemoveNonWordChars_KeepChar()
If *pWrite <> *String ; if WritePosition <> ReadPosition
*pWrite\c = *String\c ; Copy the Character from ReadPosition to WritePosition => compacting the String
EndIf
*pWrite + SizeOf(Character) ; set new Write-Position
EndMacro
If Not *String
ProcedureReturn
EndIf
While *String\c ; While Not NullChar
Select *String\c
; ----------------------------------------------------------------------
; Characters to keep
; ----------------------------------------------------------------------
; If we check for the most probably Chars first, we speed up the operation
; because we minimze the number of checks to do!
; Case 'a' To 'z' ; keep a to z
; RemoveNonWordChars_KeepChar() ; local Macro _KeppChar()
; Case 'A' To 'Z' ; keep A to Z
; RemoveNonWordChars_KeepChar()
Case '0' To '9' ; keep 0 to 9
RemoveNonWordChars_KeepChar()
; Case '_' ; keep '_'
; RemoveNonWordChars_KeepChar()
EndSelect
*String + SizeOf(Character) ; Set Pointer to NextChar
Wend
; If *pWrite is not at end of orignal *String,
; we removed some char and must write a 0-Termination as new EndOfString
If *String <> *pWrite
*pWrite\c = 0
EndIf
EndProcedure
Re: Get only trailing numbers from a string?
Code: Select all
EnableExplicit
DisableDebugger
CompilerIf #PB_Compiler_Thread
; Static String Buffer Threadsafe
Threaded StringBuffer.s{2048}
CompilerElse
; Static String Buffer
Global StringBuffer.s{2048}
CompilerEndIf
; mk-soft
Procedure.s GetNumbersFromString8(*StrPtr.Character)
Protected *result.Character
*result = @StringBuffer
While *StrPtr\c
Select *StrPtr\c
Case '0' To '9'
*result\c = *StrPtr\c
*result + SizeOf(Character)
Default
*result = @StringBuffer
EndSelect
*StrPtr + SizeOf(Character)
Wend
*result\c = #Null
ProcedureReturn StringBuffer
EndProcedure
; AZJIO (corrupts the original string)
Procedure.s GetNumbersFromString9(*Source.Character)
Protected *Ptr, flgStart = 1
While *Source\c
If *Source\c >= '0' And *Source\c <= '9'
If flgStart
*Ptr = @*Source\c
flgStart = 0
EndIf
Else
flgStart = 1
EndIf
*Source + SizeOf(Character)
Wend
If Not *Ptr
ProcedureReturn ""
EndIf
*Source = *Ptr
While *Source\c
If *Source\c > '9' Or *Source\c < '0'
*Source\c = #Null
Break
EndIf
*Source + SizeOf(Character)
Wend
ProcedureReturn PeekS(*Ptr)
EndProcedure
; AZJIO
Procedure.s GetNumbersFromString10(*Source.Character)
Protected *Ptr, flgStart = 1, length
While *Source\c
If *Source\c >= '0' And *Source\c <= '9'
If flgStart
*Ptr = @*Source\c
flgStart = 0
EndIf
Else
flgStart = 1
EndIf
*Source + SizeOf(Character)
Wend
If Not *Ptr
ProcedureReturn ""
EndIf
*Source = *Ptr
While *Source\c
If *Source\c >= '0' And *Source\c <= '9'
length + 1
Else
Break
EndIf
*Source + SizeOf(Character)
Wend
ProcedureReturn PeekS(*Ptr, length)
EndProcedure
Define demoText.s, r1.s, r2.s, r3.s, StartTime, i, t1, t2, t3
demoText = "1234Caption64"
StartTime = ElapsedMilliseconds()
For i = 0 To 1000000
r1.s = GetNumbersFromString8(@demoText)
Next
t1 = ElapsedMilliseconds() - StartTime
demoText = "1234Caption64"
StartTime = ElapsedMilliseconds()
For i = 0 To 1000000
r2.s = GetNumbersFromString9(@demoText)
Next
t2 = ElapsedMilliseconds() - StartTime
demoText = "1234Caption64"
StartTime = ElapsedMilliseconds()
For i = 0 To 1000000
r3.s = GetNumbersFromString10(@demoText)
Next
t3 = ElapsedMilliseconds() - StartTime
EnableDebugger
Debug t1
Debug t2
Debug t3
Debug r1
Debug r2
Debug r3
Re: Get only trailing numbers from a string?
@SMaag
Thanks for adding this to the discussion
I do not plan to test it for speed but it adds some additional value (so I've added it to the string functions I use)
Thanks for adding this to the discussion
I do not plan to test it for speed but it adds some additional value (so I've added it to the string functions I use)

Re: Get only trailing numbers from a string?
I have changed the behavior of the function unlike the previous ones. Previously, I was looking for the last number in the string (it may be in the middle of the string, but there are no numbers after it), now I'm looking for a number on the edge of the string (there are no other characters after the number).
Code: Select all
EnableExplicit
DisableDebugger
Procedure.s GetNumbersFromString11(*Source.Character, length)
Protected *i.Character, *SourceEnd.Character
*SourceEnd = *Source + SizeOf(Character) * (length - 1)
For *i = *SourceEnd To *Source Step - SizeOf(Character)
If *i\c > '9' Or *i\c < '0'
*i + SizeOf(Character)
ProcedureReturn PeekS(@*i\c)
EndIf
Next
ProcedureReturn PeekS(@*Source\c)
EndProcedure
Define demoText.s, r1.s, StartTime, i, t1
demoText = "1234Caption64"
StartTime = ElapsedMilliseconds()
For i = 0 To 1000000
r1.s = GetNumbersFromString11(@demoText, Len(demoText))
Next
t1 = ElapsedMilliseconds() - StartTime
demoText = "1234Caption64"
EnableDebugger
Debug t1
Debug r1
Re: Get only trailing numbers from a string?
Ok,
without string buffer . I don't know why they did it the same way as usual ...
last update
without string buffer . I don't know why they did it the same way as usual ...
last update

Code: Select all
;-TOP by mk-soft
Procedure.s GetNumbersFromString(*StrPtr.Character)
Protected *StartPtr.Character
While *StrPtr\c
Select *StrPtr\c
Case '0' To '9'
If *StartPtr = 0
*StartPtr = *StrPtr
EndIf
Default
If *StartPtr
*StartPtr = 0
EndIf
EndSelect
*StrPtr + SizeOf(Character)
Wend
If *StartPtr
ProcedureReturn PeekS(*StartPtr)
Else
ProcedureReturn ""
EndIf
EndProcedure
Define.s demoText = "1234Caption64"
r1.s = GetNumbersFromString(@demoText)
Debug r1
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive