 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
heresy
Joined: 11 Mar 2008 Posts: 291
|
Posted: Wed Jul 23, 2008 11:57 am Post subject: Range() - Range of numbers and chars, borrowed from Python |
|
|
it's equivalent to Python's built-in function Range() except :
1) Python starts from 0 but it starts from 1 so Range(10) results differently
Python : 0.1,2,3,4,5,6,7,8,9
AutoHotkey : 1,2,3,4,5,6,7,8,9,10
2) Python does not support char but it does
Python : Range("a", "z") doesn't works
AutoHotkey : Range("a", "z") results a,b,c,d,e.....v,w,x,y,z
as you can see below, Titan greatly optimized this function to have less lines but faster with additional features.
so i would like to recommend to use Titan's 2nd version.
my very first version will be kept just as a reference to give better readability.
Much appreciated to Titan and [VxE], Ian as well.
the output is Matchlist friendly (comma seperated, you can change the delimiter in Titan's version)
so you can apply it like IF Var in % Range(10)
be aware that it supports integers only which is same in Python
| Code: | MsgBox % Range(1,10) ;1,2,3,4,5,6,7,8,9,10
MsgBox % Range(10) ;1,2,3,4,5,6,7,8,9,10 (same as above)
MsgBox % Range(5,10) ;5,6,7,8,9,10
MsgBox % Range(1,10,2) ;1,3,5,7,9 (step by 2)
MsgBox % Range("a", "j") ;a,b,c,d,e,f,g,h,i,j (alphabets)
MsgBox % Range("a", "m", 2) ;a,c,e,g,i,k,m (step on alphabets as well)
MsgBox % Range("A", "J") ;A,B,C,D,E,F,G,H,I,J (upper cases)
;added features in Titan's version
MsgBox % Range(-10,10) ;supports negative numbers as well
MsgBox % Range("J") ;A,B,C,D,E,F,G,H,I,J (same as "A","J")
MsgBox % Range(1,10,1,"`n") ;Using custom delimiter
|
| Code: | ;Prototype
Range(Start, Stop="", Step=1){
if RegExMatch(Start,"i)[a-z]") && RegExMatch(Stop,"i)[a-z]")
Start := asc(Start) , Stop := asc(Stop) , alpha := 1
if !alpha {
if !Stop {
Stop := Start
Loop, %Stop%
Output .= A_Index ","
} else {
Loop, %Stop%
Output .= (!Mod(A_Index-1, Step) && A_Index >= Start) ? A_Index "," :
}
} else {
Loop, %Stop%
Output .= (!Mod(A_Index-1, Step) && A_Index >= Start) ? chr(A_Index) "," :
}
StringTrimRight, Output, Output, 1
Return Output
} |
_________________ Easy WinAPI - Dive into Windows API World
Benchmark your AutoHotkey skills at PlayAHK.com
Last edited by heresy on Thu Jul 24, 2008 12:53 am; edited 3 times in total |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5068 Location: imaginationland
|
Posted: Wed Jul 23, 2008 3:19 pm Post subject: |
|
|
You asked on IRC so here's an optimized version:
| Code: | range(x, y, c = 1, d = ",") {
If (!a := x | 0)
x := Asc(x), y := Asc(y)
Loop, % (y - x) // c + 1
r .= d . (a ? x : Chr(x)), x += c
Return, SubStr(r, 1 + StrLen(d))
} |
Haven't coded ahk in a while so my skillz are rusty. This won't work if you don't pass a stop value but that can easily be changed. It'll be interesting to see if Skan can write something shorter
Edit: here's a version that does range(10); range("j") etc.
Edit 2: typo fix
| Code: | range(x, y = "", c = 1, d = ",") {
If (!a := x | 1)
x := Asc(x), y := Asc(y)
Loop, % (y == (a ? "" : 0) ? (y := x) - x := x > 96 ? 97 : x > 64 ? 65 : 1 : y - x) // c + 1
r .= d . (a ? x : Chr(x)), x += c
Return, SubStr(r, 1 + StrLen(d))
} |
_________________
RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Last edited by Titan on Thu Jul 24, 2008 1:03 am; edited 2 times in total |
|
| Back to top |
|
 |
[VxE]
Joined: 07 Oct 2006 Posts: 1128
|
Posted: Wed Jul 23, 2008 8:54 pm Post subject: |
|
|
| Code: | range(x, y=0, c=1, d=",", i=0)
{
If (x*0="")
x := Asc(x), y := Asc(y), i := 1
r := x + (u := c * Round((y-x+0.1)/Abs(y-x+0.1)))
return % ((x=y || (x-2*u>=y)!=(r>=y))) ? (i ? Chr(x) : x) : ((i ? Chr(x) : x) d range(r, y, c, d, i))
}
msgbox % range("g","3", 3) | I think I've got it. I've tested chars and numbers where X>Y and Y>X. Tested C>1 a little bit. Not gonna bother with testing D. i is used internally... it could just be a static but that might be confusing. _________________ My Home Thread
More Common Answers: 1. It's in the FAQ 2. Ternary ( ? : ) guide 3. Post code with [code][/code] tags |
|
| Back to top |
|
 |
Ian
Joined: 15 Jul 2007 Posts: 1157 Location: Enterprise, Alabama
|
Posted: Wed Jul 23, 2008 10:47 pm Post subject: |
|
|
mod on Titan's code.
| Code: | MsgBox % range("-32") "`n" range("-32~2") "`n" range("A~J")
range(x, c = 1, d = ",") {
StringSplit, x, x, ~
a := x1+1,x1 := (a ? x1 : Asc(x1)),z := !x2 ? (x1>=97 ? 97 : x1>=65 ? 65 : 1) : (a ? x2 : Asc(x2))
Loop, % Abs(z-x1)//c+1
r .= d . (a ? (!x2 ? z : x1) : Chr((!x2 ? z : x1))),z += c,x1 += !x2 ? -c : c
Return, SubStr(r, 1 + StrLen(d))
} |
Support for one term rather than two, and negative numbers. Custom separator (~) to show two characters.
Edit:
Bugfix: LETTER~LETTER was outputting backwards.
I made another version using RegExMatch, but it does not yet support integers.
| Code: | range(x, y="") {
RegExReplace("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,"
, (!y ? x >= a ? "a" : "A" : x) . "(.*)" . (!y ? x : y), SubPat)
Return (!y ? x >= a ? "a" : "A" : x) . SubPat1 . (!y ? x : y)
} |
_________________ ScriptPad/~dieom/dieom/izwian2k7/Trikster/God
 |
|
| Back to top |
|
 |
jballi
Joined: 01 Oct 2005 Posts: 348 Location: Texas, USA
|
Posted: Sat Jul 26, 2008 9:41 pm Post subject: |
|
|
Excellent function idea. I always figured I would get around to writing something like this but now I don't have to! Thanks to everyone who contributed.  |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Sun Jul 27, 2008 7:22 pm Post subject: |
|
|
Having one function for characters and integers can work in AHK, but it is counterintuitive in typed languages, like C. I would use two different functions instead.
It is hard to tell, what is the “right” behavior when start > end (with step > 0). In many cases you want the empty list, what Titan’s function returns, but sometimes you want to list the elements backwards: range(4,1) --> 4,3,2,1.
What would you do with step = 0? It could be an error, so return the empty list, maybe except when start=stop, in which case range can be {start}.
Here is a single line function for (not necessarily integer, signed) numbers, which returns the empty string if start > end and step > 0, or start < end and step < 0, or step = 0: | Code: | NRange(a,b,d=1,s=",") { ; {a, a+d, ..., ~b}, numbers separated by s
Return (a-b)*d > 0 or !d ? "" : ("" = c:=NRange(a+d,b,d,s)) ? a : a . s . c
} | You can make it even shorter, but less clear. A similar oneliner can be written for characters by replacing number x with Chr(x), and character y with Asc(y), appropriately: | Code: | CRange(a,b,d=1,s=",") { ; {a, Chr(Asc(a)+d), ..., ~b}, chars separated by s
Return (Asc(a)-Asc(b))*d > 0 or !floor(d) ? "" : ("" = c:=CRange(Chr(Asc(a)+d),b,d,s)) ? a : a . s . c
} |
|
|
| Back to top |
|
 |
heresy
Joined: 11 Mar 2008 Posts: 291
|
Posted: Mon Jul 28, 2008 9:53 am Post subject: |
|
|
Thank Laszlo for introducing another way. seems [VxE] and You're pretty familiar with recursive function. i really need a lesson on Recursive functions. i might post FRange() later for floats when i completely got your recursive functions. Thanks! _________________ Easy WinAPI - Dive into Windows API World
Benchmark your AutoHotkey skills at PlayAHK.com |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Mon Jul 28, 2008 4:14 pm Post subject: |
|
|
| NRange works for any numbers, including floats. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|