Sign in to follow this  
Followers 0
gsx

[Solved] Create Two-Dimensional Arrays

13 posts in this topic

#1 ·  Posted (edited)

Hi,

I'm trying to create a muti-dimensional array which stores file paths. Since I'm not get used to arrays yet, I do not find the error in the following code. SciTe tells the line, $FileList[$i] = _FileListToArray($ArrayFolders[$i]) is wrong. I guess it is something to do with declaring arrays/variables?

#Include <Array.au3>

$Folders = "C:\|@MyDocumentsDir|@ScriptDir"
$ArrayFolders = StringSplit($Folders, "|")
$i = 0
Do
    $i += 1
    $FileList[$i] = _FileListToArray($ArrayFolders[$i])
Until $ArrayFolders[0] = $i
_ArrayDisplay($FileList)

I hope someone can tell what's wrong and point me to the right direction. Thanks.

Edited by gsx

Share this post


Link to post
Share on other sites



What you were trying to do is store arrays in an array which whilst possible is not really recommended. For what I think you are trying to do the simple example below should work better for you.  You had also had errors in the way you were using the @MyDocumentsDir and @ScriptDir macros.

Ask again if this does not the solution you were looking for.

#Include <Array.au3>
#Include <File.au3>

$Folders = "C:|" & @MyDocumentsDir & "|" & @ScriptDir
$ArrayFolders = StringSplit($Folders, "|")
Dim $FileList[1]
$iNumFiles = 0
$iFileIndex = 0
$iFile = 0
$i = 0
Do
    $i += 1
        $TempArray = _FileListToArray($ArrayFolders[$i])
        If IsArray($TempArray) Then
            $iNumFiles += $TempArray[0]
            ReDim $FileList[$iNumFiles]
            For $iFile = 1 To UBound($TempArray) - 1
                $FileList[$iFileIndex] = $ArrayFolders[$i] & "\" & $TempArray[$iFile]
                $iFileIndex += 1
            Next
        EndIf
Until $ArrayFolders[0] = $i
_ArrayDisplay($FileList)

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Share this post


Link to post
Share on other sites

Thanks Bowmore, your demonstration helps me a lot. ;)

I did not notice the mistake of macros. Thanks for correcting it.

What you were trying to do is store arrays in an array which whilst possible is not really recommended.

Is there a reason to avoid creating two demensional arrays? I need to give different actions to the files depending on the folder which they belong to.

Let's say there are three folders to scan. The structure is like this.

D:\Scripts\Tests\test1.au3

D:\Scripts\Tests\test2.au3

D:\Scripts\Lib\sample1.au3

D:\Scripts\Projects\project1.au3

D:\Scripts\Projects\project2.au3

D:\Scripts\Projects\project3.au3

I like the array to be,

$Folder[1] = "D:\Scripts\Tests\"
$Folder[2] = "D:\Scripts\Lib\"
$Folder[3] = "D:\Scripts\Projects\"

$FileList[1][1] = $Folder[1] & "test1.au3"
$FileList[1][2] = $Folder[1] & "test2.au3"
$FileList[2][1] = $FOlder[2] & "sample1.au3"
$FileList[3][1] = $FOlder[3] & "project1.au3"
$FileList[3][2] = $FOlder[3] & "project2.au3"
$FileList[3][3] = $FOlder[3] & "Projects\project3.au3"

My goal is to create a custom menu of these files. So I can assign them to the menu, like this way

GUICreate("My GUI Context Menu", 300, 200)
$contextmenu = GUICtrlCreateContextMenu()
$submenu[1] = GUICtrlCreateMenu($Folder[1], $contextmenu)
$submenu[2] = GUICtrlCreateMenu($Folder[2], $contextmenu)
$submenu[3] = GUICtrlCreateMenu($Folder[3], $contextmenu)
$submenu[1][1] = GUICtrlCreateMenuItem($FileList[1][1], $submenu[1])
$submenu[1][2] = GUICtrlCreateMenuItem($FileList[1][2], $submenu[1])
$submenu[2][1] = GUICtrlCreateMenuItem($FileList[2][1], $submenu[2])
$submenu[3][1] = GUICtrlCreateMenuItem($FileList[3][1], $submenu[3])
$submenu[3][2] = GUICtrlCreateMenuItem($FileList[3][2], $submenu[3])
$submenu[3][3] = GUICtrlCreateMenuItem($FileList[3][3], $submenu[3])

I'm afraid if this causes a mess.

Share this post


Link to post
Share on other sites

You may need to declare your array before using it. For e.g.,

#Include <File.au3>
#Include <Array.au3>

$Folders = "C:\" & "|" & @MyDocumentsDir & "|" & @ScriptDir
$ArrayFolders = StringSplit($Folders, "|")
_ArrayDisplay($ArrayFolders)

Local $FileList[$ArrayFolders[0]]

For $i = 1 To $ArrayFolders[0]
    $FileList[($i - 1)] = _FileListToArray($ArrayFolders[$i])
    _ArrayDisplay($FileList[($i - 1)])
Next

Share this post


Link to post
Share on other sites

Wao, it works like a charm, Fubarable. Thanks a lot.

By the way why this doesn't work? I added the last line, _ArrayDisplay($FileList) to view the whole array structure.

#Include <File.au3>
#Include <Array.au3>

$Folders = "C:|" & @MyDocumentsDir & "|" & @ScriptDir
$ArrayFolders = StringSplit($Folders, "|")
;_ArrayDisplay($ArrayFolders)

Local $FileList[$ArrayFolders[0]]

For $i = 1 To $ArrayFolders[0]
    $FileList[($i - 1)] = _FileListToArray($ArrayFolders[$i])
    ;_ArrayDisplay($FileList[($i - 1)])
Next

_ArrayDisplay($FileList)

I suppose _ArrayDisplay() can handle two-dimensional arrays like the following.

#Include <Array.au3>
Local  $arr[3][4] = [[1, 2, 3, 4], [2, 3], [3, 4, 5]]
_ArrayDisplay($arr)

Share this post


Link to post
Share on other sites

_ArrayDisplay() will display normal displayable cell content, for one and two dimensional array's

But ... it will not display a array thats stored inside a other array cell.

1) $FileList[($i - 1)] = _FileListToArray($ArrayFolders[$i])

2) ;_ArrayDisplay($FileList[($i - 1)]) ... ok

3) _ArrayDisplay($FileList) ... not ok when used with -> "$FileList[($i - 1)] = array"


"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

Wao, it works like a charm, Fubarable. Thanks a lot.

You're welcome.

By the way why this doesn't work? I added the last line, _ArrayDisplay($FileList) to view the whole array structure.

_ArrayDisplay($FileList)

I suppose _ArrayDisplay() can handle two-dimensional arrays like the following.

#Include <Array.au3>
Local  $arr[3][4] = [[1, 2, 3, 4], [2, 3], [3, 4, 5]]
_ArrayDisplay($arr)

$FileList is not a two-dimensional but rather an array of arrays, something which I gather from your first response can be dangerous to use in AutoIt (though I'm not sure why).

Share this post


Link to post
Share on other sites

Thanks MvGulik for the comment.

_ArrayDisplay() will display normal displayable cell content, for one and two dimensional array's

But ... it will not display a array thats stored inside a other array cell.

$FileList is not a two-dimensional but rather an array of arrays, something which I gather from your first response can be dangerous to use in AutoIt (though I'm not sure why).

This will totally change my understanding of arrays. I thought a set of variable structures consisting of arrays inside an array is called a two-dimensional array.

It seems I was trying to do something confusing than as I expected.

Anyways, so how can I create a two-dimensional array such as the following dynamically? I say dynamic because you know the structure of files changes every time it is scanned.

#Include <Array.au3>

Local $Folder [4]
$Folder[0] = 4
$Folder[1] = "D:\Scripts\Tests\"
$Folder[2] = "D:\Scripts\Lib\"
$Folder[3] = "D:\Scripts\Projects\"

_ArrayDisplay($Folder)

Local $FileList [3][4]
$FileList[0][0] = 3
$FileList[0][1] = $Folder[1] & "test1.au3"
$FileList[0][2] = $Folder[1] & "test2.au3"
$FileList[1][0] = 2
$FileList[1][1] = $Folder[2] & "sample1.au3"
$FileList[2][0] = 4
$FileList[2][1] = $Folder[3] & "project1.au3"
$FileList[2][2] = $Folder[3] & "project2.au3"
$FileList[2][3] = $Folder[3] & "project3.au3"

_ArrayDisplay($FileList)

Share this post


Link to post
Share on other sites

$FileList is not a two-dimensional but rather an array of arrays, something which I gather from your first response can be dangerous to use in AutoIt (though I'm not sure why).

Its not dangerous. Or at least not in a general AutoIt sense. The reason for it to discouraged seems to be that is has a speed penalty.

I personally think that speed penalty is overrated or misinterpreted. But I have no test to proof either way.

(and new users general run into trouble when trying to use array stored array's. But thats what the forums is for.)


"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

Its not dangerous. ...

Thank you for your informative and helpful answer. This is definitely what the forum is for in my book! ;)

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I thought a set of variable structures consisting of arrays inside an array is called a two-dimensional array.

It seems I was trying to do something confusing than as I expected.

Although you probably already got it.

... Here's a alternative way of looking at array's.

(warning: This might make things look complicated again. ;) )

A array can be looked at as a normal variable, but with a Adjustable size property.

How many size direction it has that can be adjusted is the dimensional property of that variable/array.

So a "local $var = 2" has zero (adjustable) dimensions. (there all fixed at size one.)

A "local $array[123] = [...]" is a variable that has one dimensions.

And a "local $array[123][456] = [[...]]" has two dimensions.

And a array inside a array is ... Erm, something else.

Edited by MvGulik

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

A array can be looked at as a normal variable, but with a Adjustable size property.

How many size direction it has that can be adjusted is the dimensional property of that variable/array.

So a "local $var = 2" has zero (adjustable) dimensions. (there all fixed at size one.)

A "local $array[123] = [...]" is a variable that has one dimensions.

And a "local $array[123][456] = [[...]]" has two dimensions.

And a array inside a array is ... Erm, something else.

Well, I'm still uncomfortable with the concept of AutoIt arrays. Yet, I'll be used to it.

Anyways, I'm almost there. Could anybody correct my code?

I placed files like the following and ran the code below. The problem is that the declaration of the array, $FileListArray[$FolderArray[0]][10]. This line means it's only limited up to 10 files to be stored in the array. Can the second dimension be dynamic? Or any better methods to achieve this would be appreciated.

C:\Scripts\Lib

C:\Scripts\Lib\sample1.au3

C:\Scripts\Projects

C:\Scripts\Projects\project1.au3

C:\Scripts\Projects\project2.au3

C:\Scripts\Projects\project3.au3

C:\Scripts\Projects\project4.au3

C:\Scripts\Tests

C:\Scripts\Tests\test1.au3

C:\Scripts\Tests\test2.au3

#include <array.au3>
#Include <File.au3>

$FolderArray = _FldrSearch("C:\Scripts\")
_ArrayDisplay($FolderArray)
;Local $FLA2ndElementMax = 2
;Local $FileListArray[$FolderArray[0]][$FLA2ndElementMax]
Local $FileListArray[$FolderArray[0]][10]   ;<- I'd like to make the second number dynamic
For $i = 1 to $FolderArray[0]
    ;Msgbox(0, "", $i & " / " & $FolderArray[0])
    $TempArray = _FileListToArray($FolderArray[$i], "*", 1)
    ;If @Error=1 Then MsgBox (0,"","No Folders Found.")
    ;If @Error=2 Then MsgBox (0,"","Error Occured.")
    ;If @Error=3 Then MsgBox (0,"","Error Occured.")
    ;If @Error=4 Then MsgBox (0,"","No Files Found.")   
    
    $thisindex = $i - 1
    _ArrayDisplay($TempArray, $FolderArray[$i])
    If IsArray($TempArray) Then 
;       if $FLA2ndElementMax < $TempArray[0] Then  ;if the maximum size exceeds, enlarge it.
;           Local $FileListArray[$FolderArray[0]][($TempArray[0]+5)] 
;       Endif
        For $i2 = 1 to $TempArray[0]
            If $i2 = 1 Then $FileListArray[$thisindex][0] = $TempArray[0] 
            $FileListArray[$thisindex][$i2] = $TempArray[$i2]
        Next
    Else
;       Msgbox(0, "", "this line is read.")
        $FileListArray[$thisindex][0] = 0
    EndIf
    $TempArray = 0
Next
_ArrayDisplay($FileListArray)

; this returns an array storing folder paths 
; written by GEOSoft http://www.autoitscript.com/forum/index.php?showtopic=59667&view=findpost&p=450173
Func _FldrSearch($szRoot, $nFlag = 1 )
    If StringRight($szRoot, 1) <> '\' Then $szRoot &= '\'
    Local $szReturn = '',  $szBuffer = '', $szPathlist = '*', $oRoot = $szRoot & '*'
        $Hfile = FileFindFirstFile ($szRoot &'*')
        If $Hfile >= 0 Then
            $szBuffer = FileFindNextFile ($Hfile)
            While NOT @Error
                If Not StringInStr($szBuffer, '.') Then $szPathlist &= $szRoot & $szBuffer & "\*"
                $szBuffer = FileFindNextFile ($Hfile)
            Wend
            FileClose ($Hfile)
        EndIf
        $szReturn = $szPathList

    If $nFlag = 1 Then
        $szPathList = StringTrimLeft($szPathlist, 1)
        $szRoot = StringLeft($szPathList, StringInStr($szPathlist, '*') -1)
        While 1
            $hFile = FileFindFirstFile ($szRoot & '*')
            If $hFile >= 0 Then
                $szBuffer = FileFindNextFile ($Hfile)
            While NOT @Error
                If Not StringInStr($szBuffer, '.') Then
                    $szPathlist &= $szRoot & $szBuffer & "\*"
                    $szReturn &= $szRoot & $szBuffer & "\*"
                EndIf
                $szBuffer = FileFindNextFile ($Hfile)
            Wend
            FileClose($hFile)
            $szPathList = StringReplace($szPathList, $szRoot, '')
            EndIf
            If $szPathList == '*' Then ExitLoop
            $szPathlist = StringTrimLeft ($szPathlist, 1)
            $szRoot = StringLeft ($szPathlist, StringInStr ($szPathlist, "*") - 1) & "\"
            $szPathlist = StringTrimLeft ($szPathlist, StringInStr ($szPathlist, "*") - 1)
        ;$szPathlist = StringReplace($szPathlist, $szRoot, '',1)
        Wend
    EndIf
    If StringLeft($szReturn, 1) = '*' Then $szReturn = StringTrimLeft($szReturn, 1)
    $szReturn = StringReplace($szReturn, '\\', '\')
    If StringRight($szReturn, 1) = '*' Then $szReturn = StringTrimRight($szReturn,1)
    $szReturn = StringSplit($oRoot & $szReturn,'*')
    If $szReturn = '*' or $szReturn = '' Then Return 0
    _ArraySort($szReturn)
    Return $szReturn
EndFunc  ;<==> _FldrSearch($szRoot)

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Finally, I got it! ;)

It was ReDim that I needed to use. It was all written here.

This code works. Thank you folks for helpful information.

#include <array.au3>
#Include <File.au3>

$FolderArray = _FldrSearch("C:\Scripts\")
_ArrayDisplay($FolderArray)
Local $FLA2ndElementMax = 2, $CurrentMaxSize = 2
Local $FileListArray[$FolderArray[0]][$FLA2ndElementMax]
For $i = 1 to $FolderArray[0]
    $TempArray = _FileListToArray($FolderArray[$i], "*", 1)
    $thisindex = $i - 1
    If IsArray($TempArray) Then 
        if $FLA2ndElementMax < $TempArray[0] AND $CurrentMaxSize < $TempArray[0] Then  ;if the maximum size exceeds, enlarge it.
            ReDim $FileListArray[$FolderArray[0]][($TempArray[0]+1)] 
            $CurrentMaxSize = $TempArray[0]
        Endif
        For $i2 = 1 to $TempArray[0]
            If $i2 = 1 Then $FileListArray[$thisindex][0] = $TempArray[0] 
            $FileListArray[$thisindex][$i2] = $TempArray[$i2]
        Next
    Else
        $FileListArray[$thisindex][0] = 0
    EndIf
    $TempArray = 0
Next
_ArrayDisplay($FileListArray)

; this returns an array storing folder paths 
; written by GEOSoft http://www.autoitscript.com/forum/index.php?showtopic=59667&view=findpost&p=450173
Func _FldrSearch($szRoot, $nFlag = 1 )
    If StringRight($szRoot, 1) <> '\' Then $szRoot &= '\'
    Local $szReturn = '',  $szBuffer = '', $szPathlist = '*', $oRoot = $szRoot & '*'
        $Hfile = FileFindFirstFile ($szRoot &'*')
        If $Hfile >= 0 Then
            $szBuffer = FileFindNextFile ($Hfile)
            While NOT @Error
                If Not StringInStr($szBuffer, '.') Then $szPathlist &= $szRoot & $szBuffer & "\*"
                $szBuffer = FileFindNextFile ($Hfile)
            Wend
            FileClose ($Hfile)
        EndIf
        $szReturn = $szPathList

    If $nFlag = 1 Then
        $szPathList = StringTrimLeft($szPathlist, 1)
        $szRoot = StringLeft($szPathList, StringInStr($szPathlist, '*') -1)
        While 1
            $hFile = FileFindFirstFile ($szRoot & '*')
            If $hFile >= 0 Then
                $szBuffer = FileFindNextFile ($Hfile)
            While NOT @Error
                If Not StringInStr($szBuffer, '.') Then
                    $szPathlist &= $szRoot & $szBuffer & "\*"
                    $szReturn &= $szRoot & $szBuffer & "\*"
                EndIf
                $szBuffer = FileFindNextFile ($Hfile)
            Wend
            FileClose($hFile)
            $szPathList = StringReplace($szPathList, $szRoot, '')
            EndIf
            If $szPathList == '*' Then ExitLoop
            $szPathlist = StringTrimLeft ($szPathlist, 1)
            $szRoot = StringLeft ($szPathlist, StringInStr ($szPathlist, "*") - 1) & "\"
            $szPathlist = StringTrimLeft ($szPathlist, StringInStr ($szPathlist, "*") - 1)
        ;$szPathlist = StringReplace($szPathlist, $szRoot, '',1)
        Wend
    EndIf
    If StringLeft($szReturn, 1) = '*' Then $szReturn = StringTrimLeft($szReturn, 1)
    $szReturn = StringReplace($szReturn, '\\', '\')
    If StringRight($szReturn, 1) = '*' Then $szReturn = StringTrimRight($szReturn,1)
    $szReturn = StringSplit($oRoot & $szReturn,'*')
    If $szReturn = '*' or $szReturn = '' Then Return 0
    _ArraySort($szReturn)
    Return $szReturn
EndFunc  ;<==> _FldrSearch($szRoot)
Edited by gsx

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0