Sign in to follow this  
Followers 0
nikink

Trouble with 3d Array

7 posts in this topic

#1 ·  Posted (edited)

Hi folks,

I have a little project where I have an Inifile like so:

[section]

IniKey1=val1.1,@keyword@keyword2,val1.2

IniKey2=val2.1,@keyword2,val2.2

IniKey3=val3.1,@keyword3@keyword2,val3.2

IniKey4=val4.1,,val4.2

IniKey5=val5.1,@keyword3@keyword4,val5.2

The Section can have a variable number of keys, and each key can have a variable number of keywords.

I want to be able to identify all keywords (including 'blank') and then be able to find all IniKeys with that keyword.

My first thought was that this would necessitate an Array of Arrays, and then I thought that a 3D Array would be more efficient / faster.

So I have a little Script that finds all the keywords and puts them into an Array.

Then I've tried going through the 2D array returned by IniReadSection and putting all the inikeys and inivalues (including the keywords) into the 2nd and 3rd dimension of the 3d Array. The Keywords becomes the 1st Dimension.

It's become very confusing!!!

My code so far kinda works, but doesn't seem to be filling the 3D array - many places are remaining unfilled, and the dimension sizes seem a bit wonky too, which explains at least some of the blank spaces...

So, I'm here to ask if anyone has either a better way to do this than a 3D array, or more experience with filling such arrays from a 1D + a 2D array combination.

My code so far is here:

;So, inireadsection to put it all into one big array
;cycle through the array and find each unique keyword

;create an array for each keyword? Not sure that's possible
#include <Array.au3>


dim $aTest[3][3] 
$aTest[0][0] = "inikey1"
$aTest[0][1] = "@word1@word2"
$aTest[0][2] = "inival1"

$aTest[1][0] = "inikey2"
$aTest[1][1] = "@word2"
$aTest[1][2] = "inival2"

$aTest[2][0] = "inikey3"
$aTest[2][1] = "@word1@word3"
$aTest[2][2] = "inival3"
Global $results[1][1][1]
dim $aKeyWords[1]

For $i = 0 To Ubound($aTest,1)-1
    $aw = StringSplit($aTest[$i][1], "@")
    ;ConsoleWrite(Ubound($aKeyWords) & @CR)
    ;ConsoleWrite(UBound($aw) & @CR)
    If UBound($aw) > 1 Then
        ReDim $aKeyWords[Ubound($aKeyWords)+UBound($aw)-1]
        ;ConsoleWrite(@TAB & Ubound($aKeyWords) & @CR)
        ;ConsoleWrite(@TAB & Ubound($aw) & @CR)
        For $j = 2 to UBound($aw)-1
        ;   ConsoleWrite($j & ":"& $aw[$j] & @CR)
            ;ConsoleWrite(@TAB & $aTest[$i][0] & @CR)
            ;ConsoleWrite(@TAB & $aTest[$i][2] & @CR)
        ;   ConsoleWrite(@TAB & Ubound($aKeyWords)+$j-UBound($aw) & @CR)
            $aKeyWords[Ubound($aKeyWords)+$j-UBound($aw)] = $aw[$j]
        Next
    EndIf   
    
Next
;_ArrayDisplay($aKeyWords)
$aKeyWords = _ArrayUnique($aKeyWords)
_ArrayDelete($aKeyWords, 0)
;_ArrayDisplay($aTest)
ReDim $results[Ubound($aKeyWords)][1][Ubound($aTest,2)];[Ubound($aTest,1)][Ubound($aTest,2)]


For $i = 0 To Ubound($results)-1
    $results[$i][0][0] = $aKeyWords[$i]
    If $results[$i][0][0] = "" Then ConsoleWrite("Results = Blank... " & @CR)
    ConsoleWrite("$i = " & $i & " : $results[$i][0][0] = " & $results[$i][0][0] & @CR)
    For $j = 0 To Ubound($aTest,1)-1
        If $results[$i][0][0] = "" Or StringInStr($aTest[$j][1], $results[$i][0][0]) Then
            ReDim $results[Ubound($results,1)][Ubound($results,2)+1][Ubound($results,3)]
            $results[$i][$j+1][0] = $aTest[$j][0]
            ConsoleWrite("$i = " & $i & " $j = " & $j & " : $results[$i][$j][0] = " & $results[$i][$j+1][0] & @CR)
            For $k = 1 To Ubound($aTest,2)-1
                $results[$i][$j+1][$k-1] = $aTest[$j][$k]
                ConsoleWrite("$i = " & $i & " $j = " & $j & " $k = " & $k & " : $results[$i][$j][$k] = " & $results[$i][$j+1][$k-1] & @CR)
            Next
        Else
            ;ConsoleWrite($results[$i][0][0] & " not found in " & $aTest[$j][0] & @CR)
        EndIf
    Next
Next

_VarDumpByRef($results, "CW")

Func _ArrayUnique(ByRef $aArray, $vDelim = '', $iBase = 1, $iUnique = 1)
    If $vDelim = '' Then $vDelim = Chr(01)
    Local $sHold
    For $iCC = $iBase To UBound($aArray) - 1
        If Not StringInStr($vDelim & $sHold, $vDelim & $aArray[$iCC] & $vDelim, $iUnique) Then _
            $sHold &= $aArray[$iCC] & $vDelim
    Next
    Return StringSplit(StringTrimRight($sHold, StringLen($vDelim)), $vDelim)
EndFunc

#cs --------------------------------------------------------------------------------------------------------------------
    Syntax:         _VarDumpByRef(ByRef $vVar, $vDumpType)
    Description:    This function displays information about the variable given, as well as it's contents (if applicable/available).
    Parameters:     $vVar       - The variable to display.
                    $vDumpType  - How to dump the variable information. See remarks for available flags.
    Return values:  String containing the information about the variable.
    Author:         Rob Saunders (rob at therks dot com)
    Remarks:        Arrays and DllStructs are fully explored and returned regardless of how many subscripts or dimensions there are.
                    This function will also properly display arrays within arrays, a feature not entirely supported by AutoIt.
                    The variable must be passed by reference for this function. This means _VarDumpByRef('Hello') will error.
                    If you want to test an expression instead of a variable use _VarDump('Expression').
#ce --------------------------------------------------------------------------------------------------------------------
Func _VarDumpByRef(ByRef $vVar, $vDumpType = Default, $sIndent = '')
    Local $sVarDump
    Local $sVarType = VarGetType($vVar)
    Switch $sVarType
        Case 'DllStruct'
            $sVarDump = 'DllStruct(' & @CRLF & _VarDumpStruct($vVar, $sIndent & @TAB) & @CRLF & $sIndent & ')'
        Case 'Array'
            $sVarDump = 'Array(' & @CRLF & _VarDumpArray($vVar, $sIndent & @TAB) & @CRLF & $sIndent & ')'
        Case 'Binary'
            $sVarDump = 'Binary(' & BinaryLen($vVar) & ') ' & $vVar
        Case 'Object'
            $sVarDump = 'Object(' & ObjName($vVar) & ')'
        Case 'String'
            $sVarDump = 'String(' & StringLen($vVar) & ') ' & $vVar
        Case Else
            $sVarDump = $sVarType & '(' & $vVar & ')'
    EndSwitch
    
    Switch $vDumpType
        Case 1, 'ConsoleWrite', 'Console', 'CW'
            ConsoleWrite($sVarDump & @CRLF)
        Case 2, 'MsgBox', 'Msg', 'Box'
            MsgBox(0x2040, 'VarDisplay', $sVarDump)
        Case 3, 'ToolTip', 'Tip'
            ToolTip($sVarDump)
        Case 4, 'Clip', 'Clipboard'
            ClipPut($sVarDump)
        Case 5, 'GUI', 'Text'
            Local Const $__WS_OVERLAPPEDWINDOW = 0xCF0000
            Local Const $__GUI_DOCKBORDERS = 102
            Local Const $__GUI_EVENT_CLOSE = -3
            Local $iGUIOnEventMode = Opt('GUIOnEventMode', 0)
            Local $guiVarDisplay = GUICreate('VarDisplay', 300, 200, Default, Default, $__WS_OVERLAPPEDWINDOW)
            GUICtrlCreateEdit($sVarDump, 0, 0, 300, 200)
                GUICtrlSetResizing(-1, $__GUI_DOCKBORDERS)
            GUISetState(@SW_SHOW, $guiVarDisplay)
            Do 
            Until GUIGetMsg() = $__GUI_EVENT_CLOSE
            GUIDelete($guiVarDisplay)
            Opt('GUIOnEventMode', $iGUIOnEventMode)
    EndSwitch
    Return $sVarDump
EndFunc

A way to visualise what's going on would be helpful, but apart from my ConsoleWrites and the _VarDumpByRef I haven't got one. ;)

Hope you can help! :)

Edited by nikink

Share this post


Link to post
Share on other sites



Hi,

so you need to see /visualize the content of your 3d array?

Mega


Scripts & functions Organize Includes Let Scite organize the include files

Yahtzee The game "Yahtzee" (Kniffel, DiceLion)

LoginWrapper Secure scripts by adding a query (authentication)

_RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...)

Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc.

MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times

Share this post


Link to post
Share on other sites

Global $results[1][1][1]

I will try to explain the humor in this declaration.

A two dimensional (2D)array can be visualized as a spreadsheet with rows and columns - as in Excel. Each cell in the

spreadsheet is a variable which can store data. So it really should be called an array of variables in which data can be stored and accessed.

A three dimensional (3D) array can be visualized as a spreadsheet with rows and columns, and on each cell of that speadsheet is a stack of more cells.

It would look like a cube made up of individual cells. So the height of the cube would be rows, the width let be columns and depth is stacks of cells.

$results[1][1][1] = $results [Number of rows] [Number of columns] [number of stacks]

You have declared one cell in three dimensional way. The only cell or variable available to store data in that 3d array is $results[0][0][0] . This is the same as an ordinary, every day, single variable, as in "Dim $aKeyWords " . It's not necessary to declare $aKeyWords[1], which is a one cell single (one) dimensional array.

For $i = 0 To Ubound($results)-1

Ubound($results) = 1

Ubound($results)-1 = 0

So, "For $i = 0 To Ubound($results)-1" is the same as "For $i = 0 To 0"

I did a forum search and came across http://www.autoitscript.com/forum/index.ph...st&p=410283

It shows a way if entering data into a 3D array I had not seen before.

One other thing, a four dimensonal array. It can be visualized as two spreadsheets.

$array[one dimension][Two dimension] [three dimension][ four dimension] On each cell of a spreadsheet is another spreadsheet.

[one dimension(row)][Two dimension(column)] is the address of the cell of another spreadsheet which has data stored at [three dimension(row)][ four dimension(column)].

Hope this helped.

Share this post


Link to post
Share on other sites

Hi folks,

I have a little project where I have an Inifile like so:

[section]

IniKey1=val1.1,@keyword@keyword2,val1.2

IniKey2=val2.1,@keyword2,val2.2

IniKey3=val3.1,@keyword3@keyword2,val3.2

IniKey4=val4.1,,val4.2

IniKey5=val5.1,@keyword3@keyword4,val5.2

The Section can have a variable number of keys, and each key can have a variable number of keywords.

I want to be able to identify all keywords (including 'blank') and then be able to find all IniKeys with that keyword.

My first thought was that this would necessitate an Array of Arrays, and then I thought that a 3D Array would be more efficient / faster.

So I have a little Script that finds all the keywords and puts them into an Array.

Then I've tried going through the 2D array returned by IniReadSection and putting all the inikeys and inivalues (including the keywords) into the 2nd and 3rd dimension of the 3d Array. The Keywords becomes the 1st Dimension.

It's become very confusing!!!

My code so far kinda works, but doesn't seem to be filling the 3D array - many places are remaining unfilled, and the dimension sizes seem a bit wonky too, which explains at least some of the blank spaces...

So, I'm here to ask if anyone has either a better way to do this than a 3D array, or more experience with filling such arrays from a 1D + a 2D array combination.

A way to visualise what's going on would be helpful, but apart from my ConsoleWrites and the _VarDumpByRef I haven't got one. :D

Hope you can help! :)

This will read an INI file and put it all in a single 3D array:

$sINI = FileOpenDialog("Read INI file to 3D array", "", "INI Files (*.ini)", 1 + 2)
If @error Then Exit
$avResults = _IniReadToArray($sINI)
_ArrayDisplay3D($avResults)

Func _IniReadToArray($sIniFile)
    ; Read all section names
    Local $avSections = IniReadSectionNames($sIniFile)
    
    ; Find max count of keys
    Local $avSecData, $iMaxCnt = 0
    For $s = 1 To $avSections[0]
        $avSecData = IniReadSection($sIniFile, $avSections[$s])
        If $avSecData[0][0] > $iMaxCnt Then $iMaxCnt = $avSecData[0][0]
    Next
    
    ; Create 3D array
    Local $avRET[$avSections[0] + 1][$iMaxCnt + 1][2]
    $avRET[0][0][0] = $avSections[0] ; Sections count for the file
    
    ; Fill array
    For $s = 1 To $avSections[0]
        $avSecData = IniReadSection($sIniFile, $avSections[$s])
        $avRET[$s][0][0] = $avSecData[0][0] ; Key count for this section
        $avRET[$s][0][1] = $avSections[$s] ; Section name
        For $k = 1 To $avSecData[0][0]
            $avRET[$s][$k][0] = $avSecData[$k][0] ; Key name
            $avRET[$s][$k][1] = $avSecData[$k][1] ; Value
        Next
    Next

    ; Return results
    Return $avRET
EndFunc   ;==>_IniReadToArray


Func _ArrayDisplay3D($avInput)
    Local $sMsg = ""
    For $a = 0 To UBound($avInput) - 1
        For $b = 0 To UBound($avInput, 2) - 1
            For $c = 0 To UBound($avInput, 3) - 1
                $sMsg &= "[" & $a & "][" & $b & "][" & $c & "] = " & $avInput[$a][$b][$c] & @CRLF
            Next
        Next
    Next
    Local $PID = Run("notepad.exe")
    WinWait("Untitled - Notepad")
    $hWin = WinGetHandle("Untitled - Notepad")
    ControlSetText($hWin, "", "Edit1", $sMsg)
EndFunc   ;==>_ArrayDisplay3D

It should have more error checking, but demonstrates the technique. The basic difference is determining the sized of the first and second dimensions ahead of time, so the 3d array is declared once at the right size. Although it has to read the file through twice to determine the max key count before dimensioning the 3D array, this is still cleaner and maybe about as fast as all the REDIM work you were doing the hard way.

;)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

I will try to explain the humor in this declaration.

A two dimensional (2D)array can be visualized as a spreadsheet with rows and columns - as in Excel. Each cell in the

spreadsheet is a variable which can store data. So it really should be called an array of variables in which data can be stored and accessed.

A three dimensional (3D) array can be visualized as a spreadsheet with rows and columns, and on each cell of that speadsheet is a stack of more cells.

That assumes the extra dimension is added at the end of the index list. If you assume the extra dimension is at the BEGINING of the list, then the analogy is cleaner:

1. A 2D array is like a spreadsheet, with Rows and Columns

2. A 3D array is like a workbook with multiple sheets, and each sheet has Rows/Columns.

Much easier that way, isn't it?

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Thankyou all! I will look through the advice you've given and try to understand it more than I do. :) Once I've done that I'll post more questions if I need to... which, given my limited understanding now, is quite likely! ;)

Share this post


Link to post
Share on other sites

I will try to explain the humor in this declaration.

A two dimensional (2D)array can be visualized as a spreadsheet with rows and columns - as in Excel. Each cell in the

spreadsheet is a variable which can store data. So it really should be called an array of variables in which data can be stored and accessed.

A three dimensional (3D) array can be visualized as a spreadsheet with rows and columns, and on each cell of that speadsheet is a stack of more cells.

It would look like a cube made up of individual cells. So the height of the cube would be rows, the width let be columns and depth is stacks of cells.

$results[1][1][1] = $results [Number of rows] [Number of columns] [number of stacks]

You have declared one cell in three dimensional way. The only cell or variable available to store data in that 3d array is $results[0][0][0] . This is the same as an ordinary, every day, single variable, as in "Dim $aKeyWords " . It's not necessary to declare $aKeyWords[1], which is a one cell single (one) dimensional array.

I dont think its humor. He/she uses ReDim to increase the size of the array.

That makes it "Advanced" instead of Humor.

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