Jump to content

Possible to create an empty array?


Recommended Posts

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) :) ?

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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
- 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!
Link to comment
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).

Edited by Siao

"be smart, drink your wine"

Link to comment
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)
Link to comment
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).
Link to comment
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)

Link to comment
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)
Link to comment
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. :)

Link to comment
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 :)

Link to comment
Share on other sites

  • 11 months later...

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.

Link to comment
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.
Link to comment
Share on other sites

  • 8 years later...

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...