Multi-level associative arrays

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
TAC109
Posts: 1098
Joined: 02 Oct 2013, 19:41
Location: New Zealand

Multi-level associative arrays

26 May 2014, 18:42

I'm trying to get to grips with multi-level associative arrays.

I find the documentation to be very brief and lacking useful examples.

How do I define an empty multi-level associative array?

How do I use the 'for' command to extract values from a multi-level associative array?

Can I enumerate the key:values in reverse order?

(I believe I understand how to insert key:value pairs into a multi-level associative array.)

Thanks for any help.
My scripts:-
XRef - Produces Cross Reference lists for scripts
ReClip - A Text Reformatting and Clip Management utility
ScriptGuard - Protects Compiled Scripts from Decompilation
I also maintain Ahk2Exe
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Multi-level associative arrays

26 May 2014, 21:20

All arrays in autohotkey are technically "associative arrays". Is your question about the for loop in reverse and/or an array declaration?
arr := { keyname1: var1, key2: valueB }
arr := { 1: blah, 2: asdf }
Is the order really important? Is it possible to store the information in reverse? Are you using numbers as Keys? If so, what have you tried?
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
TAC109
Posts: 1098
Joined: 02 Oct 2013, 19:41
Location: New Zealand

Re: Multi-level associative arrays

26 May 2014, 22:26

Sorry if I'm no being clear. I understand associative arrays.

I've got 3 questions:-
1. How do I define an empty multi-level associative array?

2. How do I use the 'for' command to extract values from a multi-level associative array?

3. Can I enumerate the key:values in reverse order?
The first two relate to multi-level associative arrays and the last is more general.

Thanks
My scripts:-
XRef - Produces Cross Reference lists for scripts
ReClip - A Text Reformatting and Clip Management utility
ScriptGuard - Protects Compiled Scripts from Decompilation
I also maintain Ahk2Exe
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Multi-level associative arrays

26 May 2014, 22:50

1. Ok, since associative arrays must have keys, this would be the closest...
An example of an "empty" 3x3 array:

Code: Select all

MySubArray_1 := { 1:{ }, 2:{ }, 3:{ } }
MySubArray_2 := { 1:{ }, 2:{ }, 3:{ } }
MySubArray_3 := { 1:{ }, 2:{ }, 3:{ } }
MyArray := { 1:MySubArray_1, 2:MySubArray_2, 3:MySubArray_3 }
2. not sure, but here is an example:

Code: Select all

MySubArray_1 := { 1:"A", 2:"B", 3:"C" }
MySubArray_2 := { 1:"D", 2:"E", 3:"F" }
MySubArray_3 := { 1:"G", 2:"H", 3:"I" }
MyArray := { 1:MySubArray_1, 2:MySubArray_2, 3:MySubArray_3 }

for every, SubArray in MyArray
	for each, item in SubArray
		MsgBox SubArray: %every%`nValue [%each%]: %item%
3. Well, in reverse could be done without much trouble if the arrays have numbers as keys...
An example: I made a neat little recursive Array-reverse function there ;)

Code: Select all

MySubArray_1 := { 1:"A", 2:"B", 3:"C" }
MySubArray_2 := { 1:"D", 2:"E", 3:"F" }
MySubArray_3 := { 1:"G", 2:"H", 3:"I" }
MyArray := { 1:MySubArray_1, 2:MySubArray_2, 3:MySubArray_3 }

MyArray:=ReverseArray(MyArray)

for every, SubArray in MyArray
	for each, item in SubArray
		MsgBox SubArray: %every%`nValue [%each%]: %item%

ReverseArray(Arr) {
	newArr := Object()
	Loop % k:=Arr.MaxIndex()
		if IsObject(Arr[A_index])
			newArr[k-(A_index-1)]:=ReverseArray(Arr[A_index])
		else
			newArr[k-(A_index-1)]:=Arr[A_index]
	return newArr
}
Cheers, hope this helps :)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
LinearSpoon
Posts: 156
Joined: 29 Sep 2013, 22:55

Re: Multi-level associative arrays

27 May 2014, 02:19

2. More generally, you simply check if each item you come to is a subarray, and if so go through a for loop on the subarray. This is one of the few algorithms it feels natural to write recursively. This serialize function is something I wrote a while back to quickly print out the contents of most objects. It might give you some ideas.

Code: Select all

msgbox % Serialize( {} )  ;Empty array
msgbox % Serialize( [1,2,3] )  ;Simple array
msgbox % Serialize( {apples:"bananas", grapes:"oranges", pickles:[1,2,3]} )  ;Associative array with a subarray
msgbox % Serialize( new example )  ;Class instance

serialize(obj)
{
  if !IsObject(obj)
    return ""
  str := "{"
  for k,v in obj
  {
    if IsObject(v)
    {
      if IsFunc(v.name)
        v := "Function"
      else
        v := serialize(v)
    }
    str .= k ":" v ", "
  }
  if IsObject(obj.base)
    str .= "base:" serialize(obj.base) ", "
  return RegexReplace(str, ", $", "") "}"
}

class example
{
  __New()
  {
    this.a := "A"
    this.b := "B"
  }
}
3. You could write a custom enumerator. This allows you to continue using for-loop syntax, and preserves the original object.

Code: Select all

;Sample data
arr := { 1:"A", 2:"B", 3:"C", cats:"dogs", zebras:"lions"}

str := "Normal Iteration"
for k,v in arr
  str .= "`n" k " = " v
Msgbox %str%

str := "Reverse Iteration"
e := new reverseEnum(arr)
while e[k,v]
  str .= "`n" k " = " v
Msgbox %str%

;Enabling arr to use reverseEnum with a for loop
str := "Reverse For Loop"
arr._NewEnum := Func("getReverseEnum")
for k,v in arr
  str .= "`n" k " = " v
Msgbox %str%

getReverseEnum(obj)
{
  return new reverseEnum(obj)
}

class reverseEnum
{
  __New(obj)
  {
    this.items := {}     ;A list of keys and values as the obj currently contains
    this.count := 0      ;Count of items found in obj
    e := ObjNewEnum(obj) ;Get a normal enumerator
    while e[k,v]         ;Get all the keys and values and save them for later
      if (k != "_NewEnum")   ;Filter enum method if it comes up...
        this.items[++this.count] := {k:k,v:v}
    this.base.__Get := this.Next  ;Enables enum[k,v] to call enum.Next(k,v)
  }

  Next(byref k, byref v)
  {
    curItem := this.items[this.count]   ;Get the current item
    k := curItem.k, v := curItem.v      ;Set byref variables
    return (this.count-- >= 1)          ;Decrement count and return whether or not this is the last item
  }
}
As a side note, I find this to be misleading: for each, item in SubArray
It's nice that it reads as an English phrase, but someone not familiar with the syntax may wonder why there is a comma when it isn't appropriate grammatically, and it gives no indication that each is actually a variable name.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Multi-level associative arrays

27 May 2014, 08:55

joedf wrote:1. Ok, since associative arrays must have keys, this would be the closest...
An example of an "empty" 3x3 array:

Code: Select all

MySubArray_1 := { 1:{ }, 2:{ }, 3:{ } }
MySubArray_2 := { 1:{ }, 2:{ }, 3:{ } }
MySubArray_3 := { 1:{ }, 2:{ }, 3:{ } }
MyArray := { 1:MySubArray_1, 2:MySubArray_2, 3:MySubArray_3 }
this is actually 3 levels deep and is a 3x3x1 array

User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Multi-level associative arrays

27 May 2014, 08:57

Haha you're right :P
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
TAC109
Posts: 1098
Joined: 02 Oct 2013, 19:41
Location: New Zealand

Re: Multi-level associative arrays

27 May 2014, 17:34

Thanks for the help everyone.

@joedf: thanks for your code that shows the basics.

@LinearSpoon: thanks for your example code, showing that the multi-level arrays can be unbalanced. As I want my object to reflect a folder with files and sub-folders, etc this will be very useful.
My scripts:-
XRef - Produces Cross Reference lists for scripts
ReClip - A Text Reformatting and Clip Management utility
ScriptGuard - Protects Compiled Scripts from Decompilation
I also maintain Ahk2Exe

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: dunnerca and 127 guests