Sign in to follow this  
Followers 0
kindlin

Viewing contents of array (and code help!)

10 posts in this topic

#1 ·  Posted (edited)

Firstly, my main goal is a simple way to view variables and arrays, more specifically, the size and what is in each cell (is cell the right word?). I generally just MsgBox(4096,"",$Var) but this gets really annoying really fast, especially when you imagine arrays which may change size throughout my coding.

I saw/found _ArraySize but the fact that it opens a new window, the format it presents the info in, its limits among other things, all bug me. So I started trying to create my own UDF to display all contents of any sized array of any number of dimensions (this second part seems to be the hard part for me) in the console. What I really wanted was to have an output similar to MatLab, which I love, but I'm having trouble getting really anywhere.

I more or less have nothing useful coded because I can't figure out how to get the program to view all the contents of an any sized array. The core of the problem is that for each new dimension it would need one further for...next statement to loop around. If I knew it was 3 dimensions I would just nest 3 for statements going from 0 to the UBound of each dimension, but It can be any dimension, so...

My thought, which I think may work, but is just confusing me, exactly like the real thing, is something based on Inception. The core would be a function calling itself (like Loop() inside my _ArrayDisplay func) as many times as there are dimensions. Each call of loop would start it on a for statement which would call Loop() for each element of that dimension until it reaches the deepest dimension where it starts ConsoleWrite'ing the actual data for viewing. I can think of many things right now that I think makes this very confusing and convoluted and I'm wondering if you guys have any ideas.

TL;DR. Is there already a way to do this somewhere else? Does my idea in the last paragraph work?

Edited by kindlin

Share this post


Link to post
Share on other sites



How about something like this?

Dim $Array[10][20]
 
;add some array data
For $r = 0 To UBound($Array, 1) - 1
    For $c = 0 To UBound($Array, 2) - 1
        $Array[$r][$c] = Random(0, 100, 1)
    Next
Next
 
get_array_info($Array)
 
Func get_array_info($myArray)
    $rows = UBound($myArray)
    $cols = UBound($myArray, 2)
    $dims = UBound($myArray, 0)
    ConsoleWrite("The " & $dims & "-dimensional array has " & $rows & " rows, " & $cols & " columns")
 
    ;get array data
    $output = ""
    For $r = 0 To UBound($myArray, 1) - 1
        $output = $output & @LF
        For $c = 0 To UBound($myArray, 2) - 1
            $output = $output & $myArray[$r][$c] & " "
        Next
    Next
    ConsoleWrite($output)
EndFunc   ;==>get_array_info

Share this post


Link to post
Share on other sites

Hi kindlin,

Not sure I'm being helpful about sizing info but have you tried _ArrayDisplay to see what is in the 'cells'?

I use it all the time to figure out what I've got in my arrays when I'm debugging.

Kind regards,

icu

Share this post


Link to post
Share on other sites

@Herb

TY for that, I see some nice code in there, and that was what when I first imagined this question I would do, to quote my OP;

I can't figure out how to get the program to view all the contents of an any sized array. The core of the problem is that for each new dimension it would need one further for...next statement to loop around (you, for example, made code that would handle a 2 dimensional array). If I knew it was 3 dimensions I would just nest 3 for statements going from 0 to the UBound of each dimension, but It can be any dimension, so...

The problem is finding a way to nest as many for statements as necessary, which is why I had to come up with some weird inception style idea. I think it would work, but my mind was becoming confused trying to get it coded in a none redundant understandable way. Hence why I'm here!

@icu

if I can't get this to work, but I bet I will, I will need to fall back onto _ArrayDisplay, but like I said in the OP, I'm not really a fan of how it does what it does, I would prefer a console representation, specifically something like MatLab, but I'll worry about specifics once I have something to work with.

Share this post


Link to post
Share on other sites

Ok! I got my inception style thing to work! It works great, but there are a couple things I would definitely like to improve, and seeing as how I got a good base I think it's possible, I just need to know what functions or what method I might try to succeed. Without further adieu, here is my UDF and a quick test function I made to test it.

The UDF:

#Include-Once

; #INDEX# =====================================================================
; Title .........: _ArrayView
; AutoIt Version : v3.3 or higher
; Language ......: English
; Description ...: Writes an array's values to the console.
; Remarks .......: Works with all sizes and shapes (or atleast that's my goal!)
; Author(s) .....: Kindlin
; =============================================================================

Func _ArrayView($Array)
    
    ;Find array demensions and demension lenghts
    Local $Dim=UBound($Array,0), $Size[$Dim+1]
    $Size[0]=$Dim ;why can't this be on the above line? It gives me an error.
    If $Size[0]=0 Then
        ConsoleWrite("ERROR: Array size is zero"&@LF)
        Exit
    EndIf
    For $i=1 To $Size[0]
        $Size[$i]=UBound($Array,$i)
    Next
    
    
    ;first thing I dislike, needing to globally create the level markers so they exist for the ConsoleWrite's
    Global $Level_1,$Level_2,$Level_3,$Level_4,$Level_5
    Local $Inception=0
    
    _Loop($Array,$Inception,$Size) ;get the ball rolling
EndFunc

;Func Loop($Array,$Dim,$Size[$Dim],$Inception)
Func _Loop($Array,$Inception,$Size)
    $Inception+=1
    Assign("Level_"&$Inception,-1) ;display contents as zero based
    ;Assign("Level_"&$Inception,0) ;display contents as "one based" for literal tinkering, will add as option later
    For $i=0 To $Size[$Inception]-1
        Assign("Level_"&$Inception,Eval("Level_"&$Inception)+1)
        If $Inception<$Size[0] Then ;if haven't reached data...
            _Loop($Array,$Inception,$Size);...must go deeper!
        Else ;once we reach data, start displaying it
            Select; THIS IS THE PART I HATE MOST!
            Case $Size[0]=1
                ConsoleWrite("["&$Level_1&"]="&$Array[$Level_1]&@LF)
            Case $Size[0]=2
                ConsoleWrite("["&$Level_1&"]["&$Level_2&"]="&$Array[$Level_1][$Level_2]&@LF)
            Case $Size[0]=3
                ConsoleWrite("["&$Level_1&"]["&$Level_2&"]["&$Level_3&"]="&$Array[$Level_1][$Level_2][$Level_3]&@LF)
            Case $Size[0]=4
                ConsoleWrite("["&$Level_1&"]["&$Level_2&"]["&$Level_3&"]["&$Level_4&"]="&$Array[$Level_1][$Level_2][$Level_3][$Level_4]&@LF)
            Case $Size[0]=5 ;this UDF is capped at 5 dimensions which is against my goal. This is also really annoying to look at.
                ConsoleWrite("["&$Level_1&"]["&$Level_2&"]["&$Level_3&"]["&$Level_4&"]["&$Level_5&"]="&$Array[$Level_1][$Level_2][$Level_3][$Level_4][$Level_5]&@LF)
            EndSelect
        EndIf
    Next
EndFunc

The test function:

#include "_ArrayView.au3"

dim $test[4]=[1,2,3,4]
_ArrayView($test)
ConsoleWrite("----||||----"&@LF)
dim $test[2][3]=[[1,2,3],[4,5,6]]
_ArrayView($test)
ConsoleWrite("----||||----"&@LF)
dim $test[2][3][2]=[[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]
_ArrayView($test)
ConsoleWrite("----||||----"&@LF)
dim $test[3][2][3][2]=[[[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]],[[[13,14],[15,16],[17,18]],[[19,20],[21,22],[23,24]]],[[[25,26],[27,28],[29,30]],[[31,32],[33,34],[35,36]]]]
_ArrayView($test)

Firstly, know that the output is a very simple display that I don't like. I'll work on that once I have the core of the program made. Secondly, the current comments are 'unprofessional,' they are just to briefly explain the program. I'll try and make better comments near the end of development.

Now for my questions. As I typed this post, as usually happens, I had some brain storms and came up with some solutions, but I am now stuck at one point. Firstly I have the 5 "Level"s as global variables to get around needing to pass them through Loop. I am going to create a single variable which I'll ReDim for each level and just pass that. Next I had (have) a very redundant select...case in the code which is obviously bad programming. I am going to turn it into a for loop which ConsoleWrite's the brackets as per my new Level variable.

The final issue is still unresolved, though I think I'm on the right track. I need to have Loop correct read an element from $Array in order to display what that element contains. The issue is the format to select an element changes based on how many dimensions the array has, so that's basically what my select is doing right now, formating the $Array[x][y][etc] based on the number of dimensions. My idea to solve this was to create the $Array[x][y][etc] as a simple string and run it through Eval(), as this accepts strings. The problem comes from that Eval can't process my element calls, it can Eval("variable") but not Eval("array") nor Eval("array[1][3]"), etc.

If someone can solve that last issue, this UDF will be looking golden. Any ideas are welcome. Thank you in advance.

Share this post


Link to post
Share on other sites

Hi kindlin,

Glad you got things going. Forgive me if you have already thought of this but have you considered taking the code already in <Array.au3> for _ArrayDisplay and modifying it to write to the console how you want it rather than a GUI? I figure most of the heavy lifting has been done by others and the leap to writing to console wouldn't be a long jump.

Kind regards,

icu

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

The code herb gave is basically _ArrayDisplay without the GUI. I could remake _ArrayDisplay in a nano second, minus the GUI, with my code right now. The thing that I really don't like about _ArrayDisplay is that it explicitly states it only works for 1 and 2 dimension arrays. My current code already works for 0-5 dimensions, but in a none robust manor. It's only this very last issue, about how can I get my UDF to find the right spot of the array for any dimension, that has me stumped.

I'm actively researching this problem, but any help or prod in a possible right direction is greatly appreciated. I'll also gladly accept the [answer] too.

EDIT: I read through most of <Array.au3> and nothing struck me as applicable. Again, every single function in that is for 1 or 2 dimensions, 90% of the UDFs set error if UBound($Array,0)=0 or if >2, so they don't really have my problem, so they didn't need to fix it.

I wish Eval could handle element calls... Though, if I was writing Eval, I don't know how I would code that either. That's more or less how I've been attempting to approach this, alas I've gotten nowhere.

EDIT2: I tried to find the source code for Eval, to see what it does exactly, but wasn't able to. I think that might help, though I honestly doubt it. Maybe it will lead me in the right direction tho, or maybe this whole thing is a wild goose chase that I can't solve. It seems that if I'm able to solve this, I could greatly robustifiy the <Array.au3> code, so I'm not sure why the CREATORS of autoit wouldn't have done this to begin with, unless it's not possible. Hmmm

Edited by kindlin

Share this post


Link to post
Share on other sites

You assemble an array reference with an arbitrary number of indexes this way:

Global $aArray[3][3][3][3]
$aArray[2][2][2][2] = "Test"


; Read last cell of an array with an arbitrary number of indexes
$sRef = "$aArray"
For $i = 1 To UBound($aArray, 0)
    $sRef &= "[" & UBound($aArray, $i) - 1 & "]"
Next
$sRead = Execute($sRef)
ConsoleWrite($sRef & " = " & $sRead & @LF)

:graduated:


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

Much thanks PsaltyDS.

I had a tester code that I used to test ways to implement Execute and Eval and I had a bug in it that caused me think it didn't work.

dim $hi[2][2]=[[3,4],[7,8]]

$str="hi["&0&"]["&1&"]"
$ans=Execute($str)

ConsoleWrite($ans&@LF)

You'll probably notice the bug about instantly... Anyways, much thanks for getting me back on the right track, I should be able to complete my code now. I knew there was no freakin way what I wanted to do was impossible; that's just not how a language that's been around this long, and that's been used by so many people, works.

Now I need to figure out how I want the info presented. Too bad we don't have n-dimensional monitors... haha.

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