AutoHotkey Community

It is currently May 27th, 2012, 11:32 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 28 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: [AHK_L] Arrays
PostPosted: October 7th, 2009, 11:32 pm 
Offline

Joined: July 9th, 2009, 9:25 pm
Posts: 120
Requires Autohotkey_L

Code:
arr := Array("b", "a", "c") ; create an array with 3 items

arr[2] := "a - new"         ; change 2nd item
arr[1] := "bac"             ; change 1st item

arr.append("new", "items")  ; add 2 more items
arr.insert(2, "xyz")        ; insert "xyz" before the 2nd item ("a - new")

Msgbox, % arr.join("`n")    ; join the array and show it in a msgbox
Msgbox, % arr.append("z").sort().reverse().join("`n")   ; append another item, sort, reverse, join

Loop, % arr.len()
   Msgbox, % arr[A_Index]


Example 2:
Code:
files := Array()

Loop, %A_WinDir%\*
   files.append(A_LoopFileName)

Msgbox, % files.sort().join("`n")

Example 3:
Code:
text = Recommended for performance and compatibility with future AutoHotkey releases.
StringSplit, textarr, text   ; create an ahk array of characters

textarr := Array().extend("textarr")   ; create an ahk_l array and extend it with the ahk array
Msgbox, % textarr.reverse().join("")


Array.ahk:
Code:
; Array Lib - temp01 - http://www.autohotkey.com/forum/viewtopic.php?t=49736
Array(p1="……", p2="……", p3="……", p4="……", p5="……", p6="……"){
   static ArrBase
   If !ArrBase
      ArrBase := Object("len", "Array_Length", "indexOf", "Array_indexOf", "join", "Array_Join"
      , "append", "Array_Append", "insert", "Array_Insert", "delete", "Array_Delete"
      , "sort", "Array_sort", "reverse", "Array_Reverse", "unique", "Array_Unique"
      , "extend", "Array_Extend", "copy", "Array_Copy", "pop", "Array_Pop")

   arr := Object("base", ArrBase)
   While (_:=p%A_Index%)!="……" && A_Index<=6
      arr[A_Index] := _
   Return arr
}

Array_indexOf(arr, val, opts="", startpos=1){
   P := !!InStr(opts, "P"), C := !!InStr(opts, "C")
   If A := !!InStr(opts, "A")
      matches := Array()
   Loop % arr.len()
      If(A_Index>=startpos)
         If(match := InStr(arr[A_Index], val, C)) and (P or StrLen(arr[A_Index])=StrLen(val))
            If A
               matches.append(A_Index)
            Else
               Return A_Index
   If A
      Return matches
   Else
      Return 0
}
Array_Join(arr, sep="`n"){
   Loop, % arr.len()
      str .= arr[A_Index] sep
   StringTrimRight, str, str, % StrLen(sep)
   return str
}
Array_Copy(arr){
   Return Array().extend(arr)
}

Array_Append(arr, p1="……", p2="……", p3="……", p4="……", p5="……", p6="……"){
   Return arr.insert(arr.len()+1, p1, p2, p3, p4, p5, p6)
}
Array_Insert(arr, index, p1="……", p2="……", p3="……", p4="……", p5="……", p6="……"){
   While (_:=p%A_Index%)!="……" && A_Index<=6
      arr._Insert(index + (A_Index-1), _)
   Return arr
}
Array_Reverse(arr){
   arr2 := Array()
   Loop, % len:=arr.len()
      arr2[len-(A_Index-1)] := arr[A_Index]
   Return arr2
}
Array_Sort(arr, func="Array_CompareFunc"){
   n := arr.len(), swapped := true
   while swapped {
      swapped := false
      Loop, % n-1 {
         i := A_Index
         if %func%(arr[i], arr[i+1], 1) > 0 ; standard ahk syntax for sort callout functions
            arr.insert(i, arr[i+1]).delete(i+2), swapped := true
      }
      n--
   }
   Return arr
}
Array_Unique(arr, func="Array_CompareFunc"){   ; by infogulch
   i := 0
   while ++i < arr.len(), j := i + 1
      while j <= arr.len()
         if !%func%(arr[i], arr[j], i-j)
            arr.delete(j) ; j comes after
         else
            j++ ; only increment to next element if not removing the current one
   Return arr
}
Array_CompareFunc(a, b, c){
   return a > b ? 1 : a = b ? 0 : -1
}

Array_Extend(arr, p1="……", p2="……", p3="……", p4="……", p5="……", p6="……"){
   While (_:=p%A_Index%)!="……" && A_Index<=6
      If IsObject(_)
         Loop, % _.len()
            arr.append(_[A_Index])
      Else
         Loop, % %_%0
            arr.append(%_%%A_Index%)
   Return arr
}
Array_Pop(arr){
   Return arr.delete(arr.len())
}
Array_Delete(arr, p1="……", p2="……", p3="……", p4="……", p5="……", p6="……"){
   While (_:=p%A_Index%)!="……" && A_Index<=6
      arr._Remove(_)
   Return arr
}

Array_Length(arr){
   len := arr._MaxIndex()
   Return len="" ? 0 : len
}


Original post


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 8th, 2010, 5:33 pm 
Offline

Joined: February 8th, 2010, 5:32 pm
Posts: 10
thank you very, very much. This is pretty much the most important addon to ahk for me. Your ruby roots are very visible ;)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 7th, 2010, 4:30 pm 
Offline

Joined: February 29th, 2008, 8:36 pm
Posts: 901
Location: Vault 7
Pretty nice. It makes certain things much easier. The only problem is that it doesn't fully support non-integer keys...

Here's an example of what I'm talking about:

Code:
arr := Array()

arr["a"] := "aval"
arr["b"] := "bval"

arr.append("new", "items")  ; add 2 more items

Loop, % arr.len()
   Msgbox, % arr[A_Index]


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 7th, 2010, 6:05 pm 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
That's because the "len" method ( which is really the _MaxIndex() method ) is based on integer keys. However, since temp01 wrote this library, there have been key upgrades to AHK_L. Try switching your loop to this:
Code:
enum := arr._NewEnum()
while enum[ k, v ]
   MsgBox, 0, Key: %k%, %v%

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 7th, 2010, 6:30 pm 
Offline

Joined: February 29th, 2008, 8:36 pm
Posts: 901
Location: Vault 7
thanks for the quick reply. I'm already using the enumerators. I was more wondering if temp01 had plans to update this nice library.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 7th, 2010, 6:36 pm 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
I suppose you could make the array elements only accept positive integer keys. Perhaps something like this:
Code:
; ArrBase.__Set := "ArrSetter"
ArrSetter( obj, key ) {
   If IsStr( key ) || ( key<1 ) {
      MsgBox, 16, Array Error, Array Keys must be a Positive Integer
      Return
   }
}
IsStr( in ) {
   Format := A_FormatInteger
   SetFormat, IntegerFast, Hex
   out := SubStr( in:=in, 1, 2 )="0x" ? False : True
   SetFormat, IntegerFast, %Format%
   Return, out
}

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 11th, 2010, 7:34 pm 
Edited it to suite my own needs:
Code:
Temp := Array()

Temp[1] := "Hello"
Temp[2] := "World"
Temp[3] := "olleH"
Temp[4] := "dlroW"

MsgBox % Temp.Join()

Temp := Array()

Temp[1] := "1101"
Temp[2] := "2407"
Temp[3] := "108"
Temp[4] := "6379"

MsgBox % Temp.Min() . "`n" . Temp.Max()

Array() {
  static ArrBase
  If !ArrBase
    ArrBase := Object("Len","Array_Len","Join","Array_Join","Add","Array_Add","Insert","Array_Insert"
                     ,"Del","Array_Del","Max","Array_Max","Min","Array_Min")

  Return Object("base",ArrBase)
}

Array_Join(Arr,Sep="|") {
  Loop, % Arr.Len()
    Str .= Arr[A_Index] . Sep
  Return SubStr(Str,1,StrLen(Str) - StrLen(Sep))
}

Array_Add(Arr,Val) {
  Return Arr.Insert(Arr.Len() + 1,Val)
}

Array_Insert(Arr,Idx,Val) {
  Return Arr._Insert(Idx,Val)
}

Array_Del(Arr,Val) {
  Arr._Remove(Val)
}

Array_Min(Arr,Mode="Value") {
  Loop, % Arr.Len()
    If (Val = "" || Arr[A_Index] < Val)
      Val := (Mode = "Value") ? Arr[A_Index] : A_Index
  Return Val
}

Array_Max(Arr,Mode="Value") {
  Loop, % Arr.Len()
    If (Val = "" || Arr[A_Index] > Val)
      Val := (Mode = "Value") ? Arr[A_Index] : A_Index
  Return Val
}

Array_Len(Arr) {
  Return Round(Arr._MaxIndex())
}


:D


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: April 12th, 2010, 9:49 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7503
Location: Australia
Revisions 49 and 50 contain some features which may be useful to this lib, especially Arrayer's version. The following is complete, working example code:
Code:
x := Object("base", Object("Ins", "ObjInsert", "Del", "ObjRemove"))
x.Ins(1, "A")
x.Ins("c")
x.Ins("C")
x.Ins(2, "B")
x.Del(3)
MsgBox % x.1 x.2 x.3
You could of course write _Insert or _Remove in place of Ins or Del. Aliases like Add or Append can be defined the same way Ins is defined. However, note that when multiple parameters are passed to _Insert, the first one is necessarily the key/index. In other words, if Add is an alias for _Insert, x.Add("A","B") will really set x.A:=B and x.Add("A","B","C") will not work at all.

Since temp01's Append accepts a list of (up to 6) values, it still has a purpose. Similarly, Delete accepts a list of keys; _Remove accepts a range (min and max), which I think is generally more useful, but Delete may still be useful in some cases.

temp01's Pop function seems unintuitive to me - it removes a single value and returns the array. "Pop" is usually used as a function of a stack, where the caller often wants the value which it just removed. Since revision 50, _Remove functions as Pop when no key is specified:
Code:
x := Object(1,"A",2,"B",3,"C")
MsgBox % x._Remove() x._Remove() x._Remove()
Unfortunately ObjRemove demands at least two parameters in the current revision, so for x.Pop() to be equivalent to x._Remove() we would need to write a wrapper function - or wait until the next update, then make "Pop" an alias for "ObjRemove".

See also: Insert, Remove.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2010, 10:49 pm 
Offline

Joined: October 13th, 2009, 10:09 pm
Posts: 1389
I believe that the indexOf function doesn't work if you store objects in the array. I believe this might be because InStr is used in indexOf and objects might return the same "string", but this is just a guess and I don't know any better way off hand.

For now, I have written a special indexOf function for my array class, but this isn't a generic one unfortunately.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2010, 1:47 am 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
fragman wrote:
... if you store objects in the array
I don't believe this was ever intended to be supported with this library. I presume temp01's intent was to create some basic 1-dimensional array functions.

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2010, 5:33 pm 
Offline

Joined: October 13th, 2009, 10:09 pm
Posts: 1389
Likely. Any suggestions how to make the function work?
I can write manual workarounds for indexOf, since I only use 2 different array types to which I added custom functions anyway, but a general solution would be nicer of course.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2010, 7:09 pm 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
A multi-dimensional array library would be much more complex. There doesn't seem to be a need for it now, but this might give you some ideas:
Code:
array := Array( "Test", Array( "A", "H", "K" ), "Array", Array( "2D", "array" ) )
MsgBox, % Array_findIndex( array, "Array" )
MsgBox, % Array_findIndex( array, "array" )

Array_findIndex( arr, val ) {
   enum := arr._newEnum()
   while enum[ k,v ]
      If IsObject( v ) {
         If ( n := Array_findIndex( v, val ) )
            Return, A_Index "," n
      }
      Else If ( val == v )
         Return, k
}

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2010, 7:20 pm 
Offline

Joined: October 13th, 2009, 10:09 pm
Posts: 1389
I don't require multidimensional arrays, but I need to be able to store any object in an array. I realize that this also implies multidimensionality, but that's not what I mean.
I just need indexOf to work with objects as array items, regardless of their content.

The other functions I used from this library all appear to work fine, atleast I haven't noticed any problems yet.

I guess I could adapt that findIndex function to recursively compare array contents to check for matches, but wouldn't simply using the = operator be enough, as it checks references on objects?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2010, 7:30 pm 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
Quote:
... indexOf to work with objects as array items ...
What exactly do you mean? ( perhaps provide what you have so far )
Code:
array := Array( "Test", object( 1, "object" ), "Array" )
MsgBox, 0, % "IsObject: " IsObject( array[2] ), % array[2]
MsgBox, % array.indexOf( "" )

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2010, 7:36 pm 
Offline

Joined: October 13th, 2009, 10:09 pm
Posts: 1389
Something like this (untested, but my code is similar, just much longer already):
Code:
o1:=Object(key,"value")
o2:=Object(key,"value2")
string:="test"
array:=Array(o1,o2,string)
index:=array.indexOf(o2) ; index is now 1 instead of 2
index:=array.indexOf(string) ; index is now 3 as it should be for the objects


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

All times are UTC [ DST ]


Who is online

Users browsing this forum: nothing and 4 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