Sign in to follow this  
Followers 0
DasBo

Possible to create an empty array?

21 posts in this topic

This may be sort of a happy problem, but I wonder if it is possible to create a real empty array, that can be filled in a loop without any special treatment of the first array element. A little example to clarify, what I mean/want:

#include <Array.au3>

; First example works, because the first array element is treated separately
Dim $foo[1]
For $i=1 To 10
    If $i=1 Then 
        $foo[0]=$i
    Else
        _ArrayAdd($foo,$i)
    EndIf
Next

; Second example would be much easier to write and read (and btw it would probably be a bit faster), 
; but doesn't work, because Dim drops an  'Array variable subscript badly formatted.' error
Dim $foo[0]
For $i=1 to 10
    _ArrayAdd($foo,$i)
Next

; Third example doesn't work either. This time _ArrayAdd() fails with @error=1, because 
; it is called with a non-array variable.
$foo=""
For $i=1 to 10
    _ArrayAdd($foo,$i)
Next

I hope you see, what I mean. Is there any way to do something like this without If/Else or extra counter variables? Just for beauty (and speed) :) ?

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

Is this what you mean?

Dim $foo[11]
Ok, I missed to note, that I want to create arrays with unknown size. The For/Next example is a bit misleading in this case. I used it to get a minimum example for filling an array with some meaningful values. :) Actually I want to use this with While/Wend loops, f.e. for reading files/lists of unknown size or similar tasks. Edited by Jeas

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Some time ago, there was the same question: http://www.autoitscript.com/forum/index.ph...st&p=392109

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

I don't think you can create a totally empy array in AutoIt.

Your simple example:

Dim $foo[0]
For $i=1 to 10
    _ArrayAdd($foo,$i)
Next

...doesn't work because you are trying to create an array with no elements: Dim $foo[0]

use this instead:

Dim $foo[1]
For $i=1 to 10
    _ArrayAdd($foo,$i)
Next

...this way you don't have to commit to an array size before hand, and the _ArrayAdd UDF will ReDim the array each time automatically.

If you are doing this on a mass-scale array with several thousand elements you will see a performance drop using _ArrayAdd, when compared to other methods.

I'm not sure why there is a problem with arrays being zero-based along with everything else in autoit, I find them really easy to use.

Edited by andybiochem
1 person likes this

- Table UDF - create simple data tables - Line Graph UDF GDI+ - quickly create simple line graphs with x and y axes (uses GDI+ with double buffer) - Line Graph UDF - quickly create simple line graphs with x and y axes (uses AI native graphic control) - Barcode Generator Code 128 B C - Create the 1/0 code for barcodes. - WebCam as BarCode Reader - use your webcam to read barcodes - Stereograms!!! - make your own stereograms in AutoIT - Ziggurat Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Box-Muller Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Elastic Radio Buttons - faux-gravity effects in AutoIT (from javascript)- Morse Code Generator - Generate morse code by tapping your spacebar!

Share this post


Link to post
Share on other sites

He could also use the ReDim function:

Dim $Array[1]

For $i = 1 To 10
    ReDim $Array[$i]
    $Array[0] = $i ; If you want to store the size of the array(not really necessary because of the UBound command).
Next

Or am I missing something?

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

ReDim is very expensive, and doing it for each change to the array in a loop is bad practice (same as _ArrayAdd).

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Ok, I missed to note, that I want to create arrays with unknown size. The For/Next example is a bit misleading in this case. I used it to get a minimum example for filling an array with some meaningful values. :) Actually I want to use this with While/Wend loops, f.e. for reading files/lists of unknown size or similar tasks.

Do you mean like this?

#include <array.au3>
Dim $foo[1]
For $i = 1 to Random(2,50,1);random number somewhere between 2 and 50
    ReDim $foo[Ubound($foo) + 1];resize the array by 1 from the previous size
    $foo[0] +=1;set the 0 element to update the count if you want to
    $foo[Ubound($foo) - 1] = "My data I want to put in " & $i;set the data to the last created element
Next

_ArrayDisplay($foo)

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Ignore This..

Edited by Kovitt

Share this post


Link to post
Share on other sites

Good code technique says to declare an array and not change the size of it. You should have a way to figure out in advance how many items you need.

Share this post


Link to post
Share on other sites

Do you mean like this?

#include <array.au3>
Dim $foo[1]
For $i = 1 to Random(2,50,1);random number somewhere between 2 and 50
    ReDim $foo[Ubound($foo) + 1];resize the array by 1 from the previous size
    $foo[0] +=1;set the 0 element to update the count if you want to
    $foo[Ubound($foo) - 1] = "My data I want to put in " & $i;set the data to the last created element
Next

_ArrayDisplay($foo)
Most solutions (also in the thread mentioned by ProgAndy) init the array with one element, using $foo[0] as an array counter later on. Of course this is a common solution to the problem. But, strictly speaking, it wastes an array element for saving an information, that can be retrieved much more reliable by using UBound(). And sometimes, the first (wasted) element even interferes with program logic, for example when handling lists, that "naturally" count from zero upward (imagine for example arrays that do something with floors in a building or age of peoples).

Share this post


Link to post
Share on other sites

ReDim is very expensive, and doing it for each change to the array in a loop is bad practice (same as _ArrayAdd).

Yes, but that's what the thread starter wanted is it not?

To create an "empty" array, and fill it up afterwards(even if it's expensive as you say)

Share this post


Link to post
Share on other sites

Most solutions (also in the thread mentioned by ProgAndy) init the array with one element, using $foo[0] as an array counter later on. Of course this is a common solution to the problem. But, strictly speaking, it wastes an array element for saving an information, that can be retrieved much more reliable by using UBound(). And sometimes, the first (wasted) element even interferes with program logic, for example when handling lists, that "naturally" count from zero upward (imagine for example arrays that do something with floors in a building or age of peoples).

Well you seem to be an expert on the matter but I'm not sure I understand what you actually want. Here is my next attempt, is this it? No counter in element 0 just the data started straight way

#include <array.au3>
Dim $foo[1]
For $i = 0 to Random(2,50,1);random number somewhere between 2 and 50
    $foo[Ubound($foo) - 1] = "My data I want to put in " & $i;set the data to the last element
    ReDim $foo[Ubound($foo) + 1];resize the array by 1 for the next bit of data
Next
    ReDim $foo[Ubound($foo) - 1];After the loop finishes resize the array by -1 from the previous size to clear the last blank element we created in anticipation of more data (wouldn't want any waste now would we!)
    
_ArrayDisplay($foo)

Share this post


Link to post
Share on other sites

Well you seem to be an expert on the matter but I'm not sure I understand what you actually want. Here is my next attempt, is this it? No counter in element 0 just the data started straight way

#include <array.au3>
Dim $foo[1]
For $i = 0 to Random(2,50,1);random number somewhere between 2 and 50
    $foo[Ubound($foo) - 1] = "My data I want to put in " & $i;set the data to the last element
    ReDim $foo[Ubound($foo) + 1];resize the array by 1 for the next bit of data
Next
    ReDim $foo[Ubound($foo) - 1];After the loop finishes resize the array by -1 from the previous size to clear the last blank element we created in anticipation of more data (wouldn't want any waste now would we!)
    
_ArrayDisplay($foo)
Yes, this is roughly, what I'm doing in practice - deleting either the first or the last element after a loop. But the additional step remains even with this solution.

If it would be possible to create a real empty array in AutoIt (in other programming languages this would be sort of a pointer), you don't need to pay any extra attention to the first element or delete the first or last element after building the array to get an array that holds nothing but the data you want to save in it.

If there is no similar solution for this problem in AutoIt, I have no problem with that. I just wanted to ask the experts in this forum, if I'm just blind or if there is really no other/better solution to this problem. Well - the latter seems to be the case. :)

Share this post


Link to post
Share on other sites

Hmm, you keep saying that you're wasting an element ([0]), IMHO you're wrong about that.

If you create an array you can use all its elements (element [0] as well) to store whatever you like. You do "waste" the element [0] when a function is returning an array and it uses [0] to store the number of elements (you can copy that array to a new one and use [0] for your purpose if the element count is bothering you).


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

I miss this Dim $array[0] as well.

It's possible in literally every computer language I've ever known except AutoIt.

An empty array is just as meaningful as an array with elements.

Using the UBound($array)-1 means you have to remember which arrays have the added [0] element and which don't.

More importantly; some AutoIt functions use element [0] for data, some use it for meta-data.

This means you cannot simply use the UBound($array)-1 trick and assume it means what you expect.

Anyway, one fix I use is to simply _ArrayDelete($array, 0) after you're done filling the array.

Share this post


Link to post
Share on other sites

How about using a delimeter string inside the loop and then a string split to create the array afterwards, works out much faster then all the redims

; Method one
$begin1 = TimerInit()

Dim $foo[1]
For $i = 1 to 1000
    ReDim $foo[Ubound($foo) + 1];resize the array by 1 from the previous size
    $foo[0] +=1;set the 0 element to update the count if you want to
    $foo[Ubound($foo) - 1] = "My data I want to put in " & $i;set the data to the last created element
Next

$dif1 = TimerDiff($begin1)

$begin2 = TimerInit()

;Method two
Local $sStore,$foo[1]
For $i = 1 to 1000
    $sStore = $sStore & "My data I want to put in " & $i & "|"
Next
$sStore = StringTrimRight($sStore,1)
$foo = StringSplit($sStore,"|")

$dif2 = TimerDiff($begin2)

MsgBox(0,"", "Method one time = " & $dif1 & @CR & "Method two time = " & $dif2)

;Method one time = 656.480362727665
;Method two time = 30.0105180965737

GDIPlusDispose - A modified version of GDIPlus that auto disposes of its own objects before shutdown of the Dll using the same function Syntax as the original.EzMySql UDF - Use MySql Databases with autoit with syntax similar to SQLite UDF.

Share this post


Link to post
Share on other sites

#20 ·  Posted

After lots of experimenting, I found a way to declare at least a 1D an empty array (doesn't use Dim):

#include <Array.au3>

Local $foo[0]
For $i=1 To 10
 _ArrayAdd($foo, $i)
Next
_ArrayDisplay($foo)

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