Jump to content

Array / For loop help


Recommended Posts

Hey,

I'm just testing some code for a bigger project when i came across something that i think i don't quit understand.

Here is the Code:

#include <array.au3>

Local $array[5];

$array[0] = "a"
$array[1] = "b"
$array[2] = "c"
$array[3] = "d"
$array[4] = "e"



For $element IN $array

    If $element = "c" Then
        _ArrayDelete($array, 2)
    EndIf
ConsoleWrite($element & @CRLF)          
Next
#cs
the above outputs
a
b
c
d
e
#ce

#cs
however this below outputs what i would expect from the above.
a
b
d
e
#ce
For $element IN $array

       ConsoleWrite($element & @CRLF)           
Next

is that working as intended? I thought For loops loop through the array one element at a time, obviously i'm wrong?

The second part of this post...

This is what I'm trying to do..

For $element IN $array

    If $element = "c" Then ; it won't just be "C" could be anything at random
        _ArrayDelete($array, $element)
    EndIf
ConsoleWrite($element & @CRLF)  
        
Next

_ArrayDelete ($array, $element) is where i'm stuck. Using a FOR loop how would i delete the element not know where in this case, "C" would be in the array?

_ArrayDelete ($array, $array[$element])
?

Any help would be greatly appreciated.

EDIT: Typo's

Edited by Steveiwonder

They call me MrRegExpMan

Link to comment
Share on other sites

  • Moderators

Steveiwonder,

You cannot use a For...In loop for this as you are trying to modify the array. From the Help file:

Autoit Array's are read-only when using For...In. While you can assign the variable inside the For...In loop a value, this change is not reflected in the array itself. To modify the contents of an array during enumeration, use a For...To loop.

So for what you are trying to do you need something like this:

#include <array.au3>

Local $array[5] = ["a", "b", "c", "d", "e"]

_ArrayDisplay($array)

For $i = 0 To UBound($array) - 1

    ConsoleWrite("Testing " & $array[$i] & @CRLF)

    If $array[$i] = "c" Then
        ConsoleWrite("Deleting " & $array[$i] & @CRLF)
        _ArrayDelete($array, $i)

        ; But we have shortened the array, so we need to do 2 things
        
        ; 1.  Adjust the index so Next keeps us in the same place (we have just replaced the index we tested with the one below
        $i -= 1
    EndIf

    ; 2.  Test that we are not over the end of the shortened array as we cannot change the end value once we have started
    If $i = UBound($array) - 1 Then ExitLoop

Next

_ArrayDisplay($array)

As you can see it is fairly simple, but you need the extra lines. Modifying arrays in a loop is pretty fraught experience - you might prefer to create a new array like this:

#include <array.au3>

Local $array[5] = ["a", "b", "c", "d", "e"]

_ArrayDisplay($array)

;  Create blank array
Global $Newarray[UBound($array)]
$iNewcount = 0

For $i = 0 To UBound($array) - 1

    ConsoleWrite("Testing " & $array[$i] & @CRLF)

    If $array[$i] <> "c" Then
        $Newarray[$iNewcount] = $array[$i]
        ConsoleWrite("Copying " & $array[$i] & @CRLF)
        $iNewcount += 1
    Else
        ConsoleWrite("Missing " & $array[$i] & @CRLF)
    EndIf

Next

; get rid of blank elements
Redim $Newarray[$iNewcount]

_ArrayDisplay($Newarray)

Your choice! :D

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Hey,

I'm just testing some code for a bigger project when i came across something that i think i don't quit understand.

Here is the Code:

#include <array.au3>

Local $array[5];

$array[0] = "a"
$array[1] = "b"
$array[2] = "c"
$array[3] = "d"
$array[4] = "e"



For $element IN $array

    If $element = "c" Then
        _ArrayDelete($array, 2)
    EndIf
ConsoleWrite($element & @CRLF)          
Next
#cs
the above outputs
a
b
c
d
e
#ce

#cs
however this below outputs what i would expect from the above.
a
b
d
e
#ce
For $element IN $array

       ConsoleWrite($element & @CRLF)           
Next
Well, putting the command ConsoleWrite($element & @CRLF) out of your If ...Endif is what makes this script goes wrong. You can go over your code step-by-step to see why. Like this:

When $element = 'c'

If $element = "c" Then This statement is true, so everything inside if ... endif will be executed.

_ArrayDelete($array, 2) delete the 3-rd (2 + 1 = 3) element of the array

EndIf

ConsoleWrite($element & @CRLF) Althought the 3-rd element of the array is deleted, the value of $element is still 'c', which result in an extra, unwanted 'c'

You can change your code a little bit like this:

#include <array.au3>

Local $array[5];

$array[0] = "a"
$array[1] = "b"
$array[2] = "c"
$array[3] = "d"
$array[4] = "e"



For $element IN $array

    If $element = "c" Then
        _ArrayDelete($array, 2)
    Else
        ConsoleWrite($element & @CRLF)
    EndIf
Next

--------------------------------------

is that working as intended? I thought For loops loop through the array one element at a time, obviously i'm wrong?

The second part of this post...

This is what I'm trying to do..

For $element IN $array

    If $element = "c" Then ; it won't just be "C" could be anything at random
        _ArrayDelete($array, $element)
    EndIf
ConsoleWrite($element & @CRLF)  
        
Next

_ArrayDelete ($array, $element) is where i'm stuck. Using a FOR loop how would i delete the element not know where in this case, "C" would be in the array?

The syntax for _Array Delete is:

_ArrayDelete(ByRef $avArray, $iElement)

Where $avArray is the array itself, and $iElement is the index of the element you want to delete. You can look up the Help Files for For..To Loop. There are more than 1 type of For Loop. So, in case the index is not a constant, you can try something like this:

For $s = 0 To 4

    If $array[$s] = "d" Then ; it won't just be "C" could be anything at random
        _ArrayDelete($array, $s)
        $s -= 1 ; this line is the same as $s = $s - 1, since we've just deleted one element of the array, we have to decrease $s by 1, so that we'll not miss any element in the array
    Else
        ConsoleWrite($array[$s] & @CRLF)
    EndIf
        
Next

Hope that I'm being clear enough. :D

Link to comment
Share on other sites

Awsome thanks you both, i've still got some problems but i'm working on them. I will ask for more help if needed.

Thanks again.

As a general point about looping through an array -

If you loop through an array and possibly delete an element as you go then you must loop from the last to the first. (Or you complicate the code as M23's example.) Otherwise you will loose track of where you are in the array and the final value for the array element will be invalid if any elements were removed.

#include <array.au3>

Local $array[5];

$array[0] = "c"
$array[1] = "b"
$array[2] = "e"
$array[3] = "c"
$array[4] = "f"



For $n = UBound($array) - 1 to 0 step -1
    If $array[$n] = "c" Then
    _ArrayDelete($array, $n)
    EndIf
Next

ConsoleWrite("result===================" & @CRLF)
For $element IN $array
 ConsoleWrite($element & @CRLF)

Next
Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

  • Moderators

martin,

How obvious now you point it out!

M23

(Hanging head in shame at not having thought of it myself :D )

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Hey,

I'm just testing some code for a bigger project when i came across something that i think i don't quit understand.

Here is the Code:

#include <array.au3>

Local $array[5];

$array[0] = "a"
$array[1] = "b"
$array[2] = "c"
$array[3] = "d"
$array[4] = "e"



For $element IN $array

    If $element = "c" Then
        _ArrayDelete($array, 2)
    EndIf
ConsoleWrite($element & @CRLF)          
Next
#cs
the above outputs
a
b
c
d
e
#ce

#cs
however this below outputs what i would expect from the above.
a
b
d
e
#ce
For $element IN $array

       ConsoleWrite($element & @CRLF)           
Next

is that working as intended? I thought For loops loop through the array one element at a time, obviously i'm wrong?

The second part of this post...

This is what I'm trying to do..

For $element IN $array

    If $element = "c" Then ; it won't just be "C" could be anything at random
        _ArrayDelete($array, $element)
    EndIf
ConsoleWrite($element & @CRLF)  
        
Next

_ArrayDelete ($array, $element) is where i'm stuck. Using a FOR loop how would i delete the element not know where in this case, "C" would be in the array?

_ArrayDelete ($array, $array[$element])
?

Any help would be greatly appreciated.

EDIT: Typo's

#include <array.au3>

Local $array[5] , $Temparray[1];

$array[0] = "a"
$array[1] = "b"
$array[2] = "c"
$array[3] = "d"
$array[4] = "e"


For $element IN $array
    If Not ($element == "c") Then
    $Temparray[UBound($Temparray) -1] = $element
    ReDim $Temparray[UBound($Temparray) + 1]
    EndIf
Next
ReDim $Temparray[UBound($Temparray) - 1]
$array = $Temparray

#cs
the above outputs
a
b
c
d
e
#ce

#cs
however this below outputs what i would expect from the above.
a
b
d
e
#ce
For $element IN $array

       ConsoleWrite($element & @CRLF)
Next
Edited by wolf9228

صرح السماء كان هنا

 

Link to comment
Share on other sites

  • 1 month 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...