AutoHotkey Community

It is currently May 26th, 2012, 10:54 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 83 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next
Author Message
PostPosted: August 25th, 2008, 5:24 am 
Offline

Joined: March 27th, 2008, 2:14 pm
Posts: 700
SimpleArray is a single variable list/array editing function library focused on speed and simplicity. It does not loop, parse or split the array when working with it, and most of the functions can finish while executing less than 20 total lines of code.

I must credit olegbl for his excellent AHKArray library, which is similar in concept, but unfortunately not compatible. Since SA is 'simple' I won't be adding some advanced features such as those found in AHKA, so if you are looking for advanced features, I must refer you to olegbl's thread. However, I am open to suggestions and if you have a feature / improvement idea that fits in the bounds of the title, it would be very welcome. :D

Note: it is still to be tested further, so please be careful with your data! If you find any bugs I would very much appreciate it reported! :)

[About]
  • Lib: These functions are library compatible, so you can save them in one of your lib folders as SA.ahk and they will be accessible without using #Include.
  • Number Index: (param name Idx may only be a number)
    For values above 0, a position relative to the beginning of the array with an index of 1. So the first element is '1', the second '2' etc.
    For values below 0, a position relative to the end of the array with an index of -1. So the last element is '-1', second to last '-2', etc.
    Zero is not used, do not pass 0 as an index. (Note that this is different from AHKA)
    If you want to add a value at the end of the array with SA_Set() use '+' as the first character and the number following will be counted as an offset from the end of the array. This allows you to add it arbitrarily farther than the end. (Note that the default index param is '+1' so you can add it to the end without specifying a number yourself)
  • Name Index: (param name nIdx May be either a number or a name.)
    A valid name is any non-blank, non-numeric string.
    If an element has a name, you can reference by it's name instead of element index.
  • Functions: New additions are in Red
    Set, Get, Del, and Trim Have all been changed to support named indexes. I also added Set_ etc functions that only take numbers, and pass the array ByRef for performance (though it is returned normally without modification)
    SA_Set( Array, Val, [nIdx="+1", Insert=false, giveName=""] ) ~ returns the new array with Val set to nIdx. If you pass a name for nIdx, the name will be preserved unless you pass something else to giveName. If you pass a number for nIdx, the element's name (if any) will be discarded. (this behaviour may be modified)
    SA_Get( Array, nIdx1=1, nIdx2="", nIdx3="", nIdx4="", nIdx5="" ) ~ returns the array element at nIdx1. Also retrieves nested arrays' elements. If you want to retrieve values more than 5 elements deep, add more params numbered sequentially.
    SA_Del( Array, nIdxFm, nIdxTo="", Count=0 ) ~ returns the new array with elements from nIdxFm to nIdxTo removed. OR you can pass nIdxFm and Count, in which case it deletes Count number of elements starting at nIdxFm
    SA_Trim( Array, nIdxFm, nIdxTo=-1 ) ~ returns the new array with everything outside of nIdxFm to nIdxTo removed.
    SA_Len( Array ) ~ returns the length of the array
    SA_IdxName( Array, Name ) ~ returns the index of Name in Array as a number
    SA_NameIdx( Array, Idx ) ~ returns the name (if any) of Idx as a string
    SA_Sort( Array, options = "") ~ returns Array sorted (SA_Sort_() is for use by this function)
    SA_Unique( array, Case = False, Whole = True ) ~ removed duplicate values from an array)
    SA_Shift( Array, nIdxFm, nIdxTo ) ~ removes element at nIdxFm and places it at nIdxTo, effectively rotating all elements between
    SA_Swap( Array, nIdx1, nIdx2 ) ~ swaps element at nIdx1 with nIdx2
    SA_Find( Array, Str, Idx=1, Case=False, Whole=True ) ~ finds Idx occurence of Str in Array
    SA_FindCnt( Array, Str, Case=False, Whole=True ) ~ finds the number of occurences of Str in Array
    SA_ConvertPsuedo( SA_AName, SA_Dims, SA_Sep = "" ) ~ converts a global-scope autohotkey array into a valid SA array automatically
    SA_ConvertDelimited( String, d ) ~ converts a character delimited string into a SA array
    SA_Join( Array, joins ) ~ joins the elements of Array with joinStr
  • Internal Use Functions:
    SA_EleOfPos( Array, Pos ) ~ returns the element index where character offset Pos occurs in Array
    SA_Idx( Array, nIdx ) ~ returns the index position of an element name or index (for simplicity and error checking)
    SA_NameExists( Array, Name ) ~ returns true if the element exists in the array
    SA_ValidName( x ) ~ returns true if the value passed is acceptable as a name
    SA_Enc( Array ) ~ returns a value ready to be used as an element
    SA_Dec( Array ) ~ returns a value ready to be used outside the array
    SA_EncRE( x ) ~ used internally, escapes a string for use in RegEx

[Code] Download

[ToDo]
    Document speed for different sizes of arrays.
    Document the functions more fully.
    Document arrays inside arrays.
    More consistent ErrorLevel
    Add demonstration script in this post

[Revision History]

_________________
Scripts - License


Last edited by infogulch on February 18th, 2010, 8:45 pm, edited 8 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 25th, 2008, 5:49 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Nice! You could get some more ideas in the 3.5 years old List manipulation functions thread. Lists are one dimensional arrays, represented as strings, with their elements separated by specific delimiters. Since the original library was written AHK evolved quite a bit. E.g. Regular Expressions could greatly reduce the code size and improve the speed.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 25th, 2008, 8:32 am 
Offline

Joined: December 13th, 2006, 7:16 am
Posts: 48
Cool! I like it! Good job on making it fast!
(I know that takes a ton of work =P)
Are you using a delimetered (|) string to store it (with encoding)?
If you want, I can work on some conversion function between our libs =)

Laszlo wrote:
Nice! You could get some more ideas in the 3.5 years old List manipulation functions thread. Lists are one dimensional arrays, represented as strings, with their elements separated by specific delimiters. Since the original library was written AHK evolved quite a bit. E.g. Regular Expressions could greatly reduce the code size and improve the speed.

Wow, I never saw the List Manipulation Functions thread when I was making the array lib haha. This looks very similar in concept, thanks for bringing it up Laszlo!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 25th, 2008, 3:59 pm 
Offline

Joined: March 27th, 2008, 2:14 pm
Posts: 700
Thank you Lazlo and olegbl! I appreciate your support. :)

Ah, the List Manipulation Functions, I will definitely have to take a close look at those, thanks Lazlo. Actually, I was trying to avoid RegEx for speed purposes, since the most demanding commands in a function are StringReplace*2, StringGetPos*2 and SubStr()*2. But if you can convince me that RegEx would help speed, I'd be more than willing to attempt it. :D
Quote:
Lists are one dimensional arrays, represented as strings, with their elements separated by specific delimiters.
I need a more descriptive definition of an "Array" as used in SA, thanks for reminding me, that's a good start. :P

Yes olegbl, a SA array is a string with the pipe char as a delimiter between elements. ("|") It also uses a special, complex encoding method I invented myself for when a user passes a value with that character to be an element. ("%d" for the delimiter, and "%e" for the encoding character: "%". Soooo complex, omg. LOLOL, jk) (see the SA_Enc/Dec functions) Because of this, you can pass one array as a value into another, and it will automatically encode it as a value. You can then get it back out as an array with no problems. You can even make it several arrays deep, and still get original values back out. (What would this be called? "Jagged arrays"?) One problem with this (vs. say using [ ] to define an array inside another) is that every time it's encoded, the string expands by 2*number of total | and % chars.

I noticed in the List manipulation thread Lazlo pointed out the built-in ahk commands If In / Contains and because those are comma delimited, I am seriously considering changing the delimiter from "|" to ",", though a simple StringReplace would make it compatible. I also had the idea to have a global delimiter variable, but I didn't want any problems with multiple included scripts setting that variable and having compatibility issues.

Wow, I feel long winded today. Yes olegbl I would love for you to make some conversion functions between our libraries. I start college today and will be rather preoccupied for some time myself, so that would be very much appreciated. :D Keep in mind though, that this lib may change frequently (at least initially), so you may want to wait a while.

:)

_________________
Scripts - License


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 25th, 2008, 8:00 pm 
Offline

Joined: December 13th, 2006, 7:16 am
Posts: 48
Yup, I was thinking of waiting for a settled format, I remember it took me months before I settled on something XD (Though I'm also going to college in about a month heh)
For your encoding/decoding format, do the %e, %d characters get recoded when included?
Code:
insert "one2|one3" at #2 of "one|two|three"
one|one2%done3|two|three
insert "one|one2%done3|two|three" at #2 of "a|b|c"

Would that make:
Code:
a|one%done2%done3%dtwo%dthree|b|c
; OR
a|one%done2%%done3%dtwo%dthree|b|c

If it's the first case, you're limited two 2D, if second, "infinite" dimensions.
You're making a very good system though, mine is a lot more burdensome and over-complicated (especially since I settled on HEXing) XD
Also for the system, back in the day I though about this option:
Code:
;Array = [one,two,[three1,three2,[three3i,three3ii],three4],four]
;Actual Format = |one|two||three1||three2|||three3i|||three3ii||three4|four

Or, replace multiple bars with : |1, |2, |3, etc...
The problem comes with:
Code:
[1,[2],[3]]
It'll think it's
Code:
[1,[2,3]]
...
Anyway, I think the Enc Dec thing works fine (as long as it re-encodes previously encoded characters (& decodes previously decoded characters). Good job on coming up with it =D
Best of luck on the project! =)


Last edited by olegbl on October 14th, 2008, 7:16 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 9th, 2008, 11:25 pm 
Offline

Joined: September 9th, 2008, 9:41 pm
Posts: 6
Code:
;Wow, I really like these array functions!
;I have two questions,
;I am currently using your array functions to do the following:

;This is my array.
TimerArray = 0|0|0|0|0|0|0|0|0|0|0|0

;This is my timer that preforms the action "Minute" every minute.
Settimer, Minute, 60000
Return

;This is the action "Minute" that uses your functions to operate on TimerArray.
Minute:
NumberofMinutes:=SA_Get(TimerArray,1)
NumberofMinutes+=1
TimerArray:=SA_Set(TimerArray,NumberofMinutes,1)
return
;So far this will increase the first index of the timer array by 1 each minute.
;So now the first question.
;How do I make one function that can do this in one step?
;IE:  Array:=SA_Set({Array to modify}, {Current Array Value + 1}, {Index to replace})

;And second question, how do I preform this opperation on a range of the array.
;IE:  Array:=SA_Set({Array to modify}, {Current Array Value + 1}, {Begining of range}, {End of range})

;I am asking this because I have a looped process.
Loop{
;Task that varies in completion time.
Counter += 1
}
;So using: Array:=SA_Set({Array to modify}, {Current Array Value + 1}, {Begining of range}, {End of range})
;I could do: TimerArray:=SA_Set(TimerArray, {Current Array Value + 1}, 0, Counter)
;So on the first loop the timer would add +1 each minute to the first index.
;On the second loop the timer would add +1 each minute to index 1 and 2.
;On the tenth loop the timer would add +1 each minute to indexes 1 through 10.

;I tried to combine and modify your SA_Get,SA_Set, and the range portion of the
;SA_Trim functions to preform this task, but got really confused in the process.
;(I'm very new to AHK. This is my first post.)

;ANY help you could provide with this would be very much apreaciated!!!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 9th, 2008, 11:50 pm 
Offline

Joined: March 27th, 2008, 2:14 pm
Posts: 700
defrostedchemist wrote:
;Wow, I really like these array functions!
Thanks!

defrostedchemist wrote:
;How do I make one function that can do this in one step?
Code:
SA_Set(TimerArray, SA_Get(TimerArray, 1)+1, 1)
Is this what you're looking for?

defrostedchemist wrote:
;So on the first loop the timer would add +1 each minute to the first index.
;On the second loop the timer would add +1 each minute to index 1 and 2.
;On the tenth loop the timer would add +1 each minute to indexes 1 through 10.

Unfortuneately, there is currently no built-in way to work on a range of an array. But try this, I think it's something like what you're asking.
Code:
;Untested:
loop 10
    loop %A_Index% ;the index of the outer loop
        SA_Set(TimerArray, SA_Get(TimerArray, A_Index)+1, A_Index)   ;this uses the index of the inner loop


Let me know if that works or not.

:)

_________________
Scripts - License


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 8th, 2008, 7:12 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Great functions! I'm going to give them a try for some of my simpler arrays in SteamLab and see how it works.

I would like to see how this compares to AHKArray (which I've been using in SteamLab) for larger, multi-dimensional arrays. Do we know how much faster the encoding is here than AHKArray's hexing?

Has this been tested on large/deep arrays to still have a good speed advantage?

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 8th, 2008, 9:37 pm 
Offline

Joined: December 13th, 2006, 7:16 am
Posts: 48
bmcclure wrote:
I would like to see how this compares to AHKArray (which I've been using in SteamLab) for larger, multi-dimensional arrays. Do we know how much faster the encoding is here than AHKArray's hexing?


I think I can answer that.
Considering SimpleArray encodes only delimiters and also doesn't need a complex parse function to access multi-dimensional arrays, it should (well, I don't know for sure, but I'm pretty sure), be *a lot* faster than AHKA. If I could use the comparison, SimpleArray would be like Unix: fast, compact, efficient while AHKA would be like Windows: slow, cumbersome, tons of features.
Though infogulch would be the real expert on the speed portion, so correct me if I'm wrong. =)


Last edited by olegbl on October 14th, 2008, 7:16 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 8th, 2008, 10:20 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Thanks; That's what I figured.

I really love the advanced functions of AHKA, however, and have never had a big problem with my apps running slow.

A lot of extra speed can never hurt though.

The only thing that's really missing from SimpleArray that I would love to see is a simple SA_Find function that locates the index of the first instance of a value in an array.

Perhaps something like SA_Find(Array, Value, Pos) where Pos could be the positive or negative index number to start searching forwards or backwards from?

I know that it would probably be the slowest function included with SA, but in my case (and I'm assuming many others), I am always trying to figure out the index of a particular value in a dynamic array and this would be a great help.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 11th, 2008, 3:28 am 
Offline

Joined: March 27th, 2008, 2:14 pm
Posts: 700
Hey guys!

That's a good idea, bmcclure. So I'm implementing element names, and ways to get their indexes. I'll probably overload most of the functions, allowing you to set and get nested arrays with one function, referencing either by name or index. It will still be fast, and I can keep my "no looping" staus. ;)

Thanks for answering olegbl. Yeah, that's about as well as I could explain it. :)

Actually, as I'm going through and rewriting I'm actually shortening these functions quite a bit. E.g. sa_set, it was ~16 lines, and I shortened it to 11. And get went from 10 to 6. Hopefully shorter = faster in this instance. :P So maybe the name addition won't add much more overhead .

I wanted to post something here just to let you guys know I'm not abandoning this. ;)

:)

_________________
Scripts - License


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 11th, 2008, 3:48 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Sounds cool! By names do you mean it will support named indexes?

If so, and with the lookup functions you're working on, I'm very excited! It could be exactly what I'm looking for for at least some of the SteamLab arrays, and if there is still a performance benefit over AHKA that would be an added bonus of maybe speeding up the application a bit.

Looking forward to the next code update :)

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 13th, 2008, 11:20 pm 
Offline

Joined: May 22nd, 2008, 12:57 am
Posts: 120
This looks cool and I will definitely be playing with it. My only suggestion would be to add a second parameter so that one can optionally pass a delimiter (obv. I will add this myself, and I know you want to keep things simple and fast, but I'm not sure how much a delimiter change will slow things down). I often have to import user entered data from a text file, and some of the entered data can contain the pipe "|" character. I'd like the option to switch to a character that they can't enter, such as A_Tab or the standard comma, or something. Again, this is something that I should be able to implement for myself, but as I'm not sure it would really slow down the code any, I thought I'd suggest it.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2008, 7:11 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Your data can contain the pipe character; that's the best part about it. The data you pass into the functions is encoded, so pipes will be encoded and decoded correctly at each level.

That is my understanding, at least; correct me if I'm wrong.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2008, 7:15 pm 
Offline

Joined: December 13th, 2006, 7:16 am
Posts: 48
Actually, from what infogulch said, I understand it as the delimiter being encoded rather than the pipe character. Which is much much more efficient.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 83 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: sks, Yahoo [Bot] and 15 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group