Jump to content

Order of array processing in a For loop?


Recommended Posts

As you can tell from my post count, I'm an AutoIt neophyte. I have a problem with a For loop and the order in which it executes, and I'm sure someone here can point out my blindness.

Basically, I use IniReadSectionNames to generate a simple array ($jobqueue). I then remove the first row of the array since I don't need the count. I run a GUICtrlCreateListView with a handle of $List1. I then execute this For loop:

For $jobid In $jobqueue
GUICtrlCreateListViewItem($jobid, $List1)
Next

The results are displayed correctly in the view, but the ordering does not match the ordering in the $jobqueue array. Hence, when I use $jobqueue[_GUICtrlListView_GetSelectedIndices($List1)] later on, the data returned doesn't match the data displayed that was clicked.

If $jobqueue contains only one row, it works. :^)

There seems to be an uncontrollable discrepancy between the order in which the rows of $jobqueue are handled in the For loop versus the order in which they exist in the array. Any ideas why? I'm sure it's something I'm doing wrong.

Oh, and yes, I searched and searched the forums and help documentation (which is excellent by the way), but I never found anyone else with a similar problem. I'm guessing this is some oddity with SelectedIndices starting at 1 but array rows starting at 0, but I'm hitting a mental block.

Link to comment
Share on other sites

I guess, your last two sentences are right on the spot. Could you please post your code or at least a little bit code that demonstrates your problem.

I would go for a For Next loop without the in!

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

Link to comment
Share on other sites

mastermindpro

You have a problem with the data. The indexes 0 or 1 is not affected, because the data is just text.

For $jobid In $jobqueue
    MsgBox(0, '???', $jobid)
    GUICtrlCreateListViewItem($jobid, $List1)
Next

For $i = 1 To $jobid[0]
    MsgBox(0, '???', $jobid[$i])
    GUICtrlCreateListViewItem($jobid[$i], $List1)
Next
Link to comment
Share on other sites

I always find myself using _ArrayToString() (with '|' delimiter) and passing it into GUICtrlCreateListViewItem(). That way, however I organize my data in the array, I know will be how it will show up in the listview. If your array starts at index 1 instead of 0, alter the start index argument in _ArrayToString() to be 1.

Edited by mechaflash213
Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

Thanks for posting a bunch of ideas, guys. I'm not sure I understand all of them, but I'll post more of my code here so you can see whether or not your ideas are applicable:

$jobqueue = IniReadSectionNames($programroot & "\utils\jobqueue.ini")
;_ArrayDisplay($jobqueue)
If IsArray($jobqueue) Then
_ArrayDelete($jobqueue, 0)
;let's build the GUI to display all queued jobs
$Form1 = GUICreate("Jobs in-process", 650, 400, (@DesktopWidth - 650) / 2, (@DesktopHeight - 400) / 2)
$Label1 = GUICtrlCreateLabel("Your Job Queue:", 16, 24, 84, 17)
$List1 = GUICtrlCreateListView("Job Number|Status|Submitted On|Complete|Priority|", 16, 48, 618, 214, $LVS_EX_FULLROWSELECT)

;loop through the jobs to build the list view items
For $jobcount In $jobqueue
$priolvl = IniRead($programroot & "\utils\jobqueue.ini", $jobcount, "priority", "")
$submittime = IniRead($programroot & "\utils\jobqueue.ini", $jobcount, "starttime", "")
$percentcomp = IniRead($programroot & "\utils\jobqueue.ini", $jobcount, "percentcomp", "")
$transferstat = IniRead($programroot & "\utils\jobqueue.ini", $jobcount, "transferstat", "")
GUICtrlCreateListViewItem($jobcount & "|" & $transferstat & "|" & $submittime & "|" & ($percentcomp * 100) & "%|" & $priolvl, $List1)
Next

;show the GUI
GUISetState(@SW_SHOW)

Later on when I use:

$jobqueue[_GUICtrlListView_GetSelectedIndices($List1)]

to get the string contents of the first column, I get the index that matches the contents of the array, not what was displayed in the ListView.

Azjio, your example doesn't seem to make sense to me, since $jobqueue is the array, not $jobid. Maybe I'm fundamentally misunderstanding how the For loop works.

Xenobiologist, I didn't see an example in the docs of using a For loop without In, so I'm not sure how I would limit the loop to the array count of $jobqueue.

Mechaflash213, that does make some sense to me, at least that the order within the string will always match the order in the array, but how do you pass that delimited string to CreateListViewItem without using some kind of loop? It seems the loop is starting at random locations within my array, so what assurances would I have that it wouldn't start at random places in a delimited string? Again, maybe I'm fundamentally missing something.

Link to comment
Share on other sites

Azjio, your example doesn't seem to make sense to me, since $jobqueue is the array, not $jobid. Maybe I'm fundamentally misunderstanding how the For loop works.

$jobqueue = IniReadSectionNames($programroot & "utilsjobqueue.ini")
If Not @error Then
    ; _ArrayDelete($jobqueue, 0)
    $Form1 = GUICreate("Jobs in-process", 650, 400)
    $Label1 = GUICtrlCreateLabel("Your Job Queue:", 16, 24, 84, 17)
    $List1 = GUICtrlCreateListView("Job Number|Status|Submitted On|Complete|Priority", 16, 48, 618, 214, $LVS_EX_FULLROWSELECT)

    For $i = 1 To $jobqueue[0]
        $priolvl = IniRead($programroot & "utilsjobqueue.ini", $jobqueue[$i], "priority", "")
        $submittime = IniRead($programroot & "utilsjobqueue.ini", $jobqueue[$i], "starttime", "")
        $percentcomp = IniRead($programroot & "utilsjobqueue.ini", $jobqueue[$i], "percentcomp", "")
        $transferstat = IniRead($programroot & "utilsjobqueue.ini", $jobqueue[$i], "transferstat", "")
        GUICtrlCreateListViewItem($jobqueue[$i] & '|' & $transferstat & '|' & $submittime & '|' & ($percentcomp * 100) & "%|" & $priolvl, $List1)
    Next

    GUISetState()
EndIf
Link to comment
Share on other sites

I started a version just before AZJIO posted. It came out very similar, but you might find the example of setting column widths and the correct placement of the $LVS_EX_FULLROWSELECT parameter useful so I'll post it as well:

#include <Array.au3>
#include <GuiListView.au3>
#include <ListviewConstants.au3>

$sINIFile = $programroot & "utilsjobqueue.ini"
$jobqueue = IniReadSectionNames($sINIFile)
If @error Then
    MsgBox(0,"","No sections found")
    Exit
EndIf
_ArrayDisplay($jobqueue)

$Form1 = GUICreate("Jobs in-process", 650, 400, (@DesktopWidth - 650) / 2, (@DesktopHeight - 400) / 2)
$Label1 = GUICtrlCreateLabel("Your Job Queue:", 16, 24, 84, 17)
$List1 = GUICtrlCreateListView("Job Name|Status|Submitted On|Complete|Priority|", 16, 48, 618, 214, Default ,$LVS_EX_FULLROWSELECT)
_GUICtrlListView_SetColumnWidth($List1, 0, 150)
_GUICtrlListView_SetColumnWidth($List1, 2, 120)

;loop through the jobs to build the list view items
For $job = 1 to $jobqueue[0]
    $priolvl = IniRead($sINIFile, $jobqueue[$job], "priority", "")
    $submittime = IniRead($sINIFile, $jobqueue[$job], "starttime", "")
    $percentcomp = IniRead($sINIFile, $jobqueue[$job], "percentcomp", "")
    $transferstat = IniRead($sINIFile, $jobqueue[$job], "transferstat", "")
    GUICtrlCreateListViewItem($jobqueue[$job] & "|" & $transferstat & "|" & $submittime & "|" & ($percentcomp * 100) & "%|" & $priolvl, $List1)
Next
;show the GUI
GUISetState(@SW_SHOW)

While 1
    $msg = GUIGetMsg()
    If $msg = -3 Then ExitLoop
WEnd

typo

Edited by Spiff59
Link to comment
Share on other sites

For $x In $y is for use with objects.

For $x To $y is a counting loop.

There's a gem right there. I'd have thought that would make it into documentation somewhere, but maybe it's too fundamental of a principle to have in documentation. Thanks for eliminating some of my neophyticity...if that's a word.

Link to comment
Share on other sites

I finally figured out what I needed to do to get this to work as I intended. Yes, I had to do a "For To" loop as many have suggested. Then, immediately after that loop, I had to delete $jobqueue[0] so that the SelectedListIndex would match up 1-1 with the $jobqueue[index]. Otherwise, I'd get a result that didn't match. The ordered loop and appropriate removal of the array count after the ordered loop seems to have solved the problem.

I'm sure that's programming 101 (which I haven't had :^) ), but the brief explanation of the difference in how For loops are processed finally unlocked it for me. Thanks to everyone for the time, attention, and code snippets. I really appreciate it.

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

  • Recently Browsing   0 members

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