Replicate() : Repeats a string N times

Post your working scripts, libraries and tools
Suresh
Posts: 35
Joined: 03 May 2016, 18:58

Replicate() : Repeats a string N times

03 Jul 2017, 07:47

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus



Most of the time, we wouldn't need a wrapper function, as it is only a single nested call.
Also the above function would fail if SetFormat is used to set Hex mode. See post by feiyue
The function explained:

To create N spaces, for eg. 12 spaces

Code: [Select all] [Download] GeSHi © Codebox Plus

Spaces := Format( "{:12}", "" )
MsgBox % "[" Spaces "]"


To create N zeroes instead, prepend a 0 to the count, eg. 012 instead of 12

Code: [Select all] [Download] GeSHi © Codebox Plus

Zeroes := Format( "{:012}", "" )
MsgBox % "[" Zeroes "]"


To repeat any other character / string,
We may use StrReplace() with one of the above results

Code: [Select all] [Download] GeSHi © Codebox Plus

Str := StrReplace( Format( "{:012}", "" ), 0, "Hello" )
MsgBox % "[" Str "]"


I chose to use the "zero version" because 0 is shorter than " " or A_Space :P
Don't know if one is faster than the other.
Last edited by Suresh on 05 Jul 2017, 06:29, edited 1 time in total.
User avatar
jNizM
Posts: 2290
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: Replicate() : Repeats a string N times

03 Jul 2017, 08:10

Alternative:

Code: [Select all] [Download] GeSHi © Codebox Plus

MsgBox % StrRepeat("Hello", 5)

StrRepeat(string, times)
{
loop % times
output .= string
return output
}
[AHK] 1.1.26.01 x64 Unicode | [WIN] 10 Pro (Version 1703) x64
My GitHub Profile | Donations are appreciated if I could help you
Helgef
Posts: 2415
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replicate() : Repeats a string N times

03 Jul 2017, 08:59

Hi Suresh ( and jNizM :wave: )
The old version seems slightly faster according to some brief testing.

For your reference, the old version was mentioned here. I came up with this function at that time,

Code: [Select all] [Download] GeSHi © Codebox Plus

strRep(str,n){
if (n<1)
return
len:=strlen(str), VarSetCapacity(nStr,n*(A_IsUnicode?2:1)*len), nStr:=str
Loop, % floor(log(n)/log(2))
nStr.=nStr
return nStr . SubStr(nStr,1,(n-2**floor(log(n)/log(2)))*len)
}

iirc, it can be faster than the old version under some circumstances; short string + very high count (like >2**16).

I prefer jNizMs version for readabillity, the need for speed is probably rare.

Cheers and thanks for sharing.
User avatar
jeeswg
Posts: 2677
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Replicate() : Repeats a string N times

03 Jul 2017, 10:06

I'd been wondering for some time if I could do this via RegEx, and I was working on it when you originally posted this function.

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus



I also collected some notes on repeating a string here:
jeeswg's strings tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=32985

I might do some benchmark tests at some point. Cheers.
feiyue
Posts: 62
Joined: 08 Aug 2014, 04:08

Re: Replicate() : Repeats a string N times

04 Jul 2017, 07:50

I did this before:

Code: [Select all] [Download] GeSHi © Codebox Plus

str:="abcd", n:=0xFF  ;---> n=255
MsgBox, % StrReplace(StrGet(VarSetCapacity(@,n,Asc("x"))*0+&@,n,0),"x",str)


I think Format() needs to consider the number of times sixteen decimal.

Code: [Select all] [Download] GeSHi © Codebox Plus

str:="abcd", n:=0xFF  ;---> n=255
MsgBox, % StrReplace(Format("{:0" . Format("{:d}",n) . "}",""),0,str)
Suresh
Posts: 35
Joined: 03 May 2016, 18:58

Re: Replicate() : Repeats a string N times

05 Jul 2017, 06:17

feiyue wrote:I did this before:

Code: [Select all] [Download] GeSHi © Codebox Plus

str:="abcd", n:=0xFF  ;---> n=255
MsgBox, % StrReplace(StrGet(VarSetCapacity(@,n,Asc("x"))*0+&@,n,0),"x",str)


Nice! :)

feiyue wrote:I think Format() needs to consider the number of times sixteen decimal.

Code: [Select all] [Download] GeSHi © Codebox Plus

str:="abcd", n:=0xFF  ;---> n=255
MsgBox, % StrReplace(Format("{:0" . Format("{:d}",n) . "}",""),0,str)


Oh! Thank you..!
Suresh
Posts: 35
Joined: 03 May 2016, 18:58

Re: Replicate() : Repeats a string N times

05 Jul 2017, 06:22

Helgef wrote:Hi Suresh ( and jNizM :wave: )


Greetings Helgef :)

The old version seems slightly faster according to some brief testing.


I know, hence I've included it.

iirc, it can be faster than the old version under some circumstances; short string + very high count (like >2**16).


I wonder under what circumstance one would need this kind of large text.

]I prefer jNizMs version for readabillity, the need for speed is probably rare.


That piece of code has been in existence for about a decade, AFAIK. :)
It will throw an error with #warn enabled


Here is one interesting use for replicating spaces

To Initialize static var with text capacity of 256 TCHARS
the regular code would be

Code: [Select all] [Download] GeSHi © Codebox Plus

Func() {
Static Var
IF not VarSetCapacity( Var )
VarSetCapacity( Var, 256 * (A_IsUnicode ? 2 : 1 ) )

DllCall( ..., "Str",Var, .. )
Return Var
}


while it can be simplified to

Code: [Select all] [Download] GeSHi © Codebox Plus

Func() {
Static Var := Format( "{:256}", "")
DllCall( ..., "Str",Var, .. )
Return Var
}
Suresh
Posts: 35
Joined: 03 May 2016, 18:58

Re: Replicate() : Repeats a string N times

05 Jul 2017, 06:23

jeeswg wrote:I could do this via RegEx,


Interesting. Thanks for sharing!
Helgef
Posts: 2415
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replicate() : Repeats a string N times

05 Jul 2017, 07:26

Suresh wrote:I wonder under what circumstance one would need this kind of large text.

When testing replicate-string functions ofc! :lol:

Suresh wrote:

Code: [Select all] [Download] GeSHi © Codebox Plus

Func() {
Static Var
IF not VarSetCapacity( Var )
VarSetCapacity( Var, 256 * (A_IsUnicode ? 2 : 1 ) )

DllCall( ..., "Str",Var, .. )
Return Var
}


while it can be simplified to

Code: [Select all] [Download] GeSHi © Codebox Plus

Func() {
Static Var := Format( "{:256}", "")
DllCall( ..., "Str",Var, .. )
Return Var
}

That is nice, although, you don't really need the if not ... for the varsetcapacity version, eg,

Code: [Select all] [Download] GeSHi © Codebox Plus

Func() {
static Var, a := VarSetCapacity( Var, 256 * (A_IsUnicode ? 2 : 1 ) )
; ...
}


@jeeswg, regarding regex. Interesting approach, I gave it a try, I don't think it is very good, only for unicode I guess,

Code: [Select all] [Download] GeSHi © Codebox Plus

regExRep(str,n){
varsetcapacity(hay,(l:=strlen(str))*n*2,1)
return regexreplace(strget(&hay,l*n), "\x{101}{" . l . "}",str)
}



@feiyue, that is very compact 8-)

Cheers.
User avatar
jeeswg
Posts: 2677
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Replicate() : Repeats a string N times

05 Jul 2017, 07:36

The idea behind the RegExReplace approach, was to have very readable, very short one-liners for certain limited situations (not a general approach), that only used one existing function, not a custom function, that directly returned a value for use in an expression. Also a bit of time travel, for the times when AHK didn't have Format or StrReplace.
User avatar
jeeswg
Posts: 2677
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Replicate() : Repeats a string N times

12 Jul 2017, 01:44

I moved some content out to a new post:
string hacks - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=34390

This is the best I have for 'StrRept', but none of them is pretty:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

Last edited by jeeswg on 12 Jul 2017, 15:02, edited 6 times in total.
Helgef
Posts: 2415
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replicate() : Repeats a string N times

12 Jul 2017, 02:46

@ jeeswg
I never though of using strsplit to count occurances, nifty, but I'd imagine StrReplace(...OutputVarCount) would perform better (did you benchmark?), and to me, it is the more natural choise.
Instead of Object(...).HasKey, maybe you find this more readable,

Code: [Select all] [Download] GeSHi © Codebox Plus

var:="hello"
Msgbox, % {hello:1,jeeswg:1}.haskey(var)

Ofc, for the object() method you can do object(var*).haskey(...).

I think we are sort of off-topic here.

@ Topic (sort of).
I think I improved my earlier version of a replicate function,

Code: [Select all] [Download] GeSHi © Codebox Plus

strRep(str,n,ByRef out){
static WA:=A_IsUnicode?2:1
len:=strlen(str), VarSetCapacity(out,n*WA*(len+1)), out:=str
Loop, % flog:=floor(log(n)/log(2))
out.=out
out.=strget(&out,(n-2**flog)*len)
return
}

I also think the old version (see the first post by Suresh) might be sligthly improved by this,

Code: [Select all] [Download] GeSHi © Codebox Plus

Replicate( Str, Count, byref out ) { ; By SKAN / CD:12-04-2011
; www.autohotkey.com/community/viewtopic.php?p=435990#435990
VarSetCapacity( S, Count * ( A_IsUnicode ? 2:1 ), 1 )
StringReplace, out, S, % SubStr( S,1,1 ), %Str%, All
Return
}

Cheers.
Suresh
Posts: 35
Joined: 03 May 2016, 18:58

Re: Replicate() : Repeats a string N times

17 Jul 2017, 04:38

Helgef wrote:I also think the old version (see the first post by Suresh) might be sligthly improved by this,


Code: [Select all] [Download] GeSHi © Codebox Plus

Replicate( "Hello", 2, Out )
MsgBox % Out


The minimum capacity for VasrSetCapacity() is 3 :)
Helgef
Posts: 2415
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replicate() : Repeats a string N times

17 Jul 2017, 05:39

Hello Suresh.
I didn't know, it's weird I didn't test for such a simple example :oops: Quick reading the manual on VarSetCapacity I didn't see it mentioned. It seems to be 3 for ANSI and 6 for unicode :think:. Anyways, I try to correct my mistake,

Code: [Select all] [Download] GeSHi © Codebox Plus

Replicate( Str, Count, byref out ) {
static WA:=A_IsUnicode ? 2:1
static replaceChar:= A_IsUnicode ? chr(0x101):chr(1)
VarSetCapacity( S, Count * WA, 1 )
out:=rtrim(StrReplace(S,replaceChar,str,,count),replaceChar)
}
Suresh
Posts: 35
Joined: 03 May 2016, 18:58

Re: Replicate() : Repeats a string N times

17 Jul 2017, 05:56

Helgef wrote:It seems to be 3 for ANSI and 6 for unicode


True. VarSetCapacity() works differently in ANSI and UNICODE.
Also, it differs with existing vs new variable

Try this in ANSI and UNICODE:

Code: [Select all] [Download] GeSHi © Codebox Plus

Loop 1000
{
Cap := VarSetCapacity( Var, A_Index, 0 )
If ( Cap <> A_Index )
MsgBox % A_Index " = " Cap
}
Helgef
Posts: 2415
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replicate() : Repeats a string N times

17 Jul 2017, 06:31

Good observations, thanks :thumbup:
User avatar
jeeswg
Posts: 2677
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Replicate() : Repeats a string N times

11 Sep 2017, 05:33

I have a similar function, and it gave me a surprise when the number was 0 or below, so I fixed my function as follows:

Code: [Select all] [Download] GeSHi © Codebox Plus

JEE_StrRept(vText, vNum)
{
if (vNum <= 0)
return
return StrReplace(Format("{:" vNum "}","")," ",vText)
;return StrReplace(Format("{:0" vNum "}",0),0,vText)
}


This example illustrates the problem:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus


Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 20 guests