Confusing associative arrays Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Zelna
Posts: 8
Joined: 28 Jul 2016, 09:15

Confusing associative arrays

03 Apr 2018, 16:02

Hello,
for the sake of this question, lets assume that I have images with these names in a certain folder: buttonA.bmp, buttonA2.bmp, buttonA3.bmp, buttonB.bmp, buttonB2.bmp.
I am trying to create an associative array at the beginning of my script, which will read the names of pictures and create an array of them so that my script can know "by itself" how many images of certain things are there. I am trying to make it work this way because right now, whenever i create a new picture, lets say buttonB3.bmp, I need to add some code in my script so that it would include the newly added picture in the search for buttonB. And its becoming quite cumbersome. So the way I tried to make it work was like this:

Code: Select all

class ButtonPictures
{
	__new()
	{
		IniRead, sectionNames, files\buttons.ini ;i have the names of all buttons in buttons.ini
		
		Loop, parse, sectionNames, `n ;retrieves the name of each button
		{
			secName := A_LoopField
			Loop, Files, files\%secName%??.bmp ;searches for all images starting with buttons name
			{
				%secName% := {(a_index): A_LoopFileName} ;this is what confuses me and is probably the core of the failure
				msgbox, % %secName%[a_index] ;this works as expected, shows the name of the image
			}
			
			msgbox, % %secName%[1] ;this does not show anything
		}
		
		msgbox, % buttonA[2] ;this also does not show anything
	}
	
}
I am trying to contain the whole array within a class, and i know it should have

Code: Select all

this.
prefix, but

Code: Select all

this.%secName%
is not allowed. If its not possible to contain it within a class, I could always just put it in a function and then return the whole array. But it would be nicer if there would be some way to make the class work.
So, again, my question is: what should I need to change in the code above to successfully create an associative array where the name of the button is the name of array, keys are just integers and values are the names of pictures. For example:

Code: Select all

buttonA{1: buttonA.bmp, 2: buttonA2.bmp, 3: buttonA3.bmp}
.
Thank you in advance :)
MaxAstro
Posts: 557
Joined: 05 Oct 2016, 13:00

Re: Confusing associative arrays

03 Apr 2018, 16:12

Just as an idea, you could create a two dimensional associative array. So for example, PictureArray[ButtonA][1] would be the name of the first ButtonA, and PictureArray[ButtonB][3] would be the third ButtonB. That should be relatively easy to add to on the fly.

EDIT: It also has the advantage that you can do for example for key, value in PictureArray[ButtonA] if you need to iterate through all the buttons of a certain type.
TQu

Re: Confusing associative arrays

03 Apr 2018, 22:30

Code: Select all

/* buttons
[sectionNames]
buttonA
buttonB
buttonC
[]
*/
inifile=%A_ScriptDir%\buttons.ahk
Loopfile=%A_ScriptDir%\files\*.bmp
IniRead, a,% inifile , sectionNames
for b,c in StrSplit(a,"`n") {
	%c%:={}
	Loop, Files,% Loopfile
		if ( InStr(A_LoopFileName,c)) {
			%c%[A_Index] := A_LoopFileName
		}
}
d:=buttonA.MaxIndex()
for a,b in buttonA
( (a<=d-1)?(e.=a ": "b ", "):((a=d)?(e.=a ": "b):0) )
MsgBox,% "buttonA:={"e "}"
. "`n" buttonA[2]
Zelna
Posts: 8
Joined: 28 Jul 2016, 09:15

Re: Confusing associative arrays

04 Apr 2018, 02:08

Thank you both for replies!
I combined both answers and came up with this:

Code: Select all

class ButtonPictures
{
	__new()
	{
		IniRead, sectionNames, files\buttons.ini
		
		Loop, parse, sectionNames, `n
		{
			secName := A_LoopField
			this.pictureArray[secName]:={}
			Loop, Files, files\%secName%??.bmp
			{
				this.pictureArray[secName][a_index] := A_LoopFileName
			}
		}
	}
}
and now I can do this:

Code: Select all

pics := new ButtonPictures
msgbox, % pics.pictureArray.ButtonB.2
, which works great :D Now I no longer need to update code with every new picture:

Code: Select all

myImagesearch(pics.pictureArray.ButtonB.length(), pics.pictureArray.ButtonB, 1x, 1y, 0, 0, a_screenWidth, a_ScreenHeight, 20)

myImagesearch(image_count, array_name, byref 1x, byref 1y, Lx, Ly, Rx, Ry, variation:=0, trans:=0)
{
	if (trans || variation)
	{
		loop % image_count
		{
			image := "files\" . array_name[a_index]
			if (trans)
				image := "*trans" . trans . " " . image
				
			if (variation)
				image := "*" . variation . " " . image
			
			imagesearch, 1x, 1y, %Lx%, %Ly%, %Rx%, %Ry%, %image%
			if (!errorlevel)
				return 0
		}
	}
	else
	{
		loop % image_count
		{
			image := "files\" . array_name[a_index]
			imagesearch, 1x, 1y, %Lx%, %Ly%, %Rx%, %Ry%, %image%
			if (!errorlevel)
				return 0
		}
	}
}
very convenient, Thank you :)
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Confusing associative arrays

04 Apr 2018, 03:40

The issue was that you replaced the array you stored the pictures in every time you added a picture.
Only the last picture was stored inside the array.
If Arr[A_Index] := value is not an option for adding new values you might want to use arr.push( value )
This automatically adds value to the array no matter how many other keys there are inside.
The key it is stored at is always the highest number inside the array.
Recommends AHK Studio
Zelna
Posts: 8
Joined: 28 Jul 2016, 09:15

Re: Confusing associative arrays

04 Apr 2018, 04:22

Thank you, I think i got it now. I went even further and created this:

Code: Select all

class images
{
	__new()
	{
		num = 1
		Loop, Files, files\*.bmp
		{
			imageName := A_LoopFileName
			stringtrimRight, imageName, imageName, 4 ;removes ".bmp" from filename
			StringRight, rightMostChar, imageName, 1 
			if rightMostChar not in 1,2,3,4,5,6,7,8,9,0 ;checks if the last character is a number
			{
				this.picArr[imageName]:={} ;creates an array
				num = 1
			}
			else
			{
				stringtrimRight, imageName, imageName, 1 ;removes the number from image name
			}
			
			this.picArr[imageName][num] := A_LoopFileName ;adds picture name to array
			++num
		}
	}
}
I think what confused me was the fact that sometimes it is needed to use "[]" and sometimes "%%" when creating arrays. For example, when I was trying to create the above code, first I made it outside of a class and then it worked like this:

Code: Select all

num = 1
Loop, Files, files\*.bmp
{
	imageName := A_LoopFileName
	stringtrimRight, imageName, imageName, 4
	StringRight, rightMostChar, imageName, 1
	if rightMostChar not in 1,2,3,4,5,6,7,8,9,0
	{
		%imageName%:={}
		num = 1
	}
	else
	{
		stringtrimRight, imageName, imageName, 1
	}
			
	%imageName%[num] := A_LoopFileName
	++num
}
but when I tried to make it two dimensional, like this:

Code: Select all

num = 1
Loop, Files, files\*.bmp
{
	imageName := A_LoopFileName
	stringtrimRight, imageName, imageName, 4
	StringRight, rightMostChar, imageName, 1
	if rightMostChar not in 1,2,3,4,5,6,7,8,9,0
	{
		picArr%imageName%:={} ;none of these would work
		;picArr[imageName]:={} 
		num = 1
	}
	else
	{
		stringtrimRight, imageName, imageName, 1
	}
			
	picArr%imageName%[num] := A_LoopFileName
	;picArr[imageName][num] := A_LoopFileName
	++num
}
it just didn't work out. Im still a bit confused about this, why in a class this works

Code: Select all

this.picArr[imageName]:={}
but outside of the class, almost the same thing does not work:

Code: Select all

picArr[imageName]:={}
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Confusing associative arrays  Topic is solved

04 Apr 2018, 05:04

Within a class This is an already existing object. Outside of a class, you have to define picArr as an object before you can add items:

Code: Select all

picArr := [] ; or {} or Array() or Object()
num = 1
Loop, Files, files\*.bmp
{
	imageName := A_LoopFileName
	stringtrimRight, imageName, imageName, 4
	StringRight, rightMostChar, imageName, 1
	if rightMostChar not in 1,2,3,4,5,6,7,8,9,0
	{
		picArr[imageName]:={} 
		num = 1
	}
	else
	{
		stringtrimRight, imageName, imageName, 1
	}
	picArr[imageName][num] := A_LoopFileName
	++num
}
MaxAstro
Posts: 557
Joined: 05 Oct 2016, 13:00

Re: Confusing associative arrays

05 Apr 2018, 08:19

Zelna wrote:I think what confused me was the fact that sometimes it is needed to use "[]" and sometimes "%%" when creating arrays.
These are two completely different things. If you use %% you are creating what are called pseudo-arrays. Pseudo-arrays aren't actually arrays at all; the variables in the pseudo-array are not linked to each other in any real way. It's just a collection of variables with dynamically assigned names.

Arrays created with [] or {} are actual arrays; the elements of the array are all part of a single array variable, and you can use the built-in functions of the array class with them (such as array.push and array.lenth) as well as iterating through them with for loops.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Kodakku and 378 guests