Repeat / dupplicate a string

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Repeat / dupplicate a string

Post by Olli »

Code: Select all

Procedure.S RepStr(A$, N.I = 1)
   Define R$, I
   For I = 1 To N
      R$ + A$
   Next
   ProcedureReturn R$
EndProcedure
Example :

Code: Select all

Debug RepStr("ha", 3)
; Displays "hahaha"
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Repeat / dupplicate a string

Post by BarryG »

You can do this until the team decides whether to add your request. It's much faster than building a string with For/Next, and doesn't have the overhead of a procedure.

Code: Select all

Macro RepStr(text,num)
  ReplaceString(Space(num)," ",text)
EndMacro

Debug RepStr("ha",3) ; Displays "hahaha"
Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Re: Repeat / dupplicate a string

Post by Olli »

Clever !
User avatar
NicTheQuick
Addict
Addict
Posts: 1227
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Repeat / dupplicate a string

Post by NicTheQuick »

It would be phenomenal to overload the * operator for this like so:

Code: Select all

Debug "ha" * 3 ;outputs "hahaha"
But maybe I am just a little bit influenced by years of working with Python. :lol:
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Re: Repeat / dupplicate a string

Post by Olli »

How is interpreted

Code: Select all

"ha" * "hi"
1) "ha" ?
2) "hi" ?
3) "haha" ?
4) "hihi" ?
5) error ?
User avatar
NicTheQuick
Addict
Addict
Posts: 1227
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Repeat / dupplicate a string

Post by NicTheQuick »

Code: Select all

>>> "ha" * "hi"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'str'
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Re: Repeat / dupplicate a string

Post by kenmo »

You can do this until the team decides whether to add your request. It's much faster than building a string with For/Next, and doesn't have the overhead of a procedure.
Nice simple one-liner :)

Now you got me interested, here's a procedure which seems to be faster than the Macro (surely it varies with the input and output lengths, though)

Code: Select all

Procedure.S RepStr(A$, N.I = 1)
   Define R$, I
   For I = 1 To N
      R$ + A$
   Next
   ProcedureReturn R$
EndProcedure

Macro RepStr2(text,num)
  ReplaceString(Space(num)," ",text)
EndMacro

Procedure.s RepStr3(A$, N.I = 1)
  Protected R$
  If A$ = ""
  ElseIf (N > 1)
    R$ = A$ + Space(Len(A$) * (N-1))
    Copied = StringByteLength(A$)
    Remain = Copied * (N-1)
    While (#True)
      If (Remain > Copied)
        CopyMemory(@R$, @R$ + Copied, Copied)
        Remain - Copied
        Copied + Copied
      Else
        CopyMemory(@R$, @R$ + Copied, Remain)
        Break
      EndIf
    Wend
  ElseIf (N = 1)
    R$ = A$
  EndIf
  ProcedureReturn R$
EndProcedure

CompilerIf #PB_Compiler_Debugger
  CompilerError "Turn off Debugger for accurate speed comparison"
CompilerEndIf

OpenConsole()

TestStr.s = "ha"
NumRepeats.i = 5000

UseMD5Fingerprint()

PrintN("Method 1")
NumLoops.i = 10 ; limit the number of loops because this method is much slower!
Start = ElapsedMilliseconds()
For j = 1 To NumLoops
  Test$ = RepStr(TestStr, NumRepeats)
Next j
Stop = ElapsedMilliseconds()
PrintN(StrF((Stop - Start)/NumLoops, 3) + " ms per loop")
PrintN("Hash: " + Fingerprint(@Test$, StringByteLength(Test$), #PB_Cipher_MD5))
PrintN("")

PrintN("Method 2")
NumLoops = 1000
Start = ElapsedMilliseconds()
For j = 1 To NumLoops
  Test$ = RepStr2(TestStr, NumRepeats)
Next j
Stop = ElapsedMilliseconds()
PrintN(StrF((Stop - Start)/NumLoops, 3) + " ms per loop")
PrintN("Hash: " + Fingerprint(@Test$, StringByteLength(Test$), #PB_Cipher_MD5))
PrintN("")

PrintN("Method 3")
NumLoops = 1000
Start = ElapsedMilliseconds()
For j = 1 To NumLoops
  Test$ = RepStr3(TestStr, NumRepeats)
Next j
Stop = ElapsedMilliseconds()
PrintN(StrF((Stop - Start)/NumLoops, 3) + " ms per loop")
PrintN("Hash: " + Fingerprint(@Test$, StringByteLength(Test$), #PB_Cipher_MD5))
PrintN("")

Input()
CloseConsole()
User avatar
helpy
Enthusiast
Enthusiast
Posts: 552
Joined: Sat Jun 28, 2003 12:01 am

Re: Repeat / dupplicate a string

Post by helpy »

If you use longer strings, than the macro is the fastest ...
Windows 10 / Windows 7
PB Last Final / Last Beta Testing
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Re: Repeat / dupplicate a string

Post by kenmo »

Seems to be true! I'm impressed by ReplaceString() :o

I only used a sample size of 1 string :)
Little John
Addict
Addict
Posts: 4527
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Repeat / dupplicate a string

Post by Little John »

By the way ... In case you just want to repeat 1 character you can use the following, which is very fast:

Code: Select all

Macro RepeatChar (_count_, _char_)
   LSet("", _count_, _char_)
EndMacro
User avatar
mk-soft
Always Here
Always Here
Posts: 5402
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Repeat / dupplicate a string

Post by mk-soft »

BarryG wrote:You can do this until the team decides whether to add your request. It's much faster than building a string with For/Next, and doesn't have the overhead of a procedure.

Code: Select all

Macro RepStr(text,num)
  ReplaceString(Space(num)," ",text)
EndMacro

Debug RepStr("ha",3) ; Displays "hahaha"
Optimize for big strings. First parameter allocate now enough space for the result string :wink:

Code: Select all

Macro RepBigStr(text,num)
  ReplaceString(Space(num * Len(text)), Space(Len(text)), text)
EndMacro

r1.s = RepBigStr("No12345678",3) ; Displays "hahaha"
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
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Repeat / dupplicate a string

Post by BarryG »

mk-soft, what do you mean? My example works with large strings.

Code: Select all

Macro RepBigStr(text,num)
  ReplaceString(Space(num)," ",text)
EndMacro

r1.s = RepBigStr("1234567890",1000)
Debug r1
Debug Len(r1) ; 10000, as expected.
User avatar
mk-soft
Always Here
Always Here
Posts: 5402
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Repeat / dupplicate a string

Post by mk-soft »

With you the empty string is at first only three characters large when num = 3, and must be increased each time the string 'text' is replaced.

I don't know if this works faster, because the search string is bigger when replacing the string 'text'.
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
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Repeat / dupplicate a string

Post by BarryG »

I think I once read that ReplaceString is very fast and optimized anyway. Even with 100000 repeats it's instant, with no pre-padding needed.

Code: Select all

RepBigStr("1234567890",100000)
[Edit] Found it -> viewtopic.php?p=244260#p244260
User avatar
mk-soft
Always Here
Always Here
Posts: 5402
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Repeat / dupplicate a string

Post by mk-soft »

Thats right,

Is no longer measurable on my CPU anyway. :D
Intel(R) Core(TM) i7-8700B CPU @ 3.20GHz
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
Post Reply