Sign in to follow this  
Followers 0
kor

do I need 2 loops to accomplish this or can I do it in 1?

17 posts in this topic

I have an array of data.

FirstName,LastName,Location,Action

Bob,Smith,Denver,Enroll

John,Jones,Denver,Withdraw

Jacob,Jackson,Denver,Withdraw

Mike,Thomas,Denver,Enroll

John,Jones,LasVegas,Enroll

From the above sample data I need to do the following.

Read data, If action = enroll then do 1, If action = withdraw then do 2.

Simple enough, but the monkey wrench gets thrown in if someone shows up twice.. once with a withdraw and again with an enroll. In this case if you look at John Jones he is first withdrawn, then enrolled. That situation is called a "move". Problem is the program that spits out the data can't call it a move... it has to withdraw from the old location and enroll in the new.

What I need to do is basically loop through the entire array during every loop step to check to see if the person the script is currently working on shows up again somewhere else in the array and meets the conditions of first being withdrawn and then being enrolled. Because then the script would assign an action of "move" and then do 3.

So I'm wondering if what I'm trying to do can be accomplished in 1 loop. I don't think I can. In my head I need 2 loops. The first loop goes through each row and does the normal action, but during every step in the first loop it goes through another loop to re-read the entire array searching for another instance of the first loop step. Does that make sense?

Share this post


Link to post
Share on other sites



Hi kor,

did you think of _ArraySearch()? So you don't need to loop the array a second time.


Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler]

Share this post


Link to post
Share on other sites

Have you thought of assigning an original index column to each row (1 loop through original data), then using _ArraySort to sort by name? Then you could just compare the original index of the entries to determine the order in which their actions took place.

Share this post


Link to post
Share on other sites

I dont care about the order of the action. If a user shows up twice, I have to do something different than if they only show up once. Makes no difference where in the array they show up twice, just the fact they show up twice at all changes what needs to be done.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

#include <array.au3>

Dim $a[6]
$a[0] = 5
$a[1] = "Bob,Smith,Denver,Enroll"
$a[2] = "John,Jones,Denver,Withdraw"
$a[3] = "Jacob,Jackson,Denver,Withdraw"
$a[4] = "Mike,Thomas,Denver,Enroll"
$a[5] = "John,Jones,LasVegas,Enroll"

Dim $b[$a[0] + 1]
$b[0] = $a[0]
For $i = 1 To $a[0]
    $a_t = StringSplit($a[$i],",")
    $b[$i] = $a_t[1] & "," & $a_t[2]
    ConsoleWrite($b[$i] & @CRLF)
Next
_ArrayDisplay($b)
For $i = 1 To $a[0]
    $a_t = StringSplit($a[$i],",")

    $rc = _ArraySearch($b, $a_t[1] & "," & $a_t[2], $i + 1)

    If $rc > 0 Then
        ConsoleWrite("C" & @CRLF)
        $a[$rc] = $a_t[1] & "," & $a_t[2]  & "," & $a_t[3]  & ",Done"
    ElseIf $a_t[4] = "Enroll" Then
        ConsoleWrite("A" & @CRLF)
    ElseIf $a_t[4] = "Withdraw" Then
        ConsoleWrite("B" & @CRLF)
    EndIf
Next

Result:

A

C

B

A

Hope this helps. Couldn't do it without 2 Loops either, but at least they are not nested. :unsure:

Edited by Hannes123

Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler]

Share this post


Link to post
Share on other sites

Check out _ArrayFindAll - will return an array of matches in a given array.

Share this post


Link to post
Share on other sites

Here's another way of doing it

#include <Array.au3>
Global $Array[5][4] = [["Bob", "Smith", "Denver", "Enroll"],["John", "Jones", "Denver", "Withdraw"],["Jacob", "Jackson", "Denver", "Withdraw"],["Mike", "Thomas", "Denver", "Enroll"],["John", "Jones", "LasVegas", "Enroll"]]

For $I = 4 To 0 Step -1
    Switch $Array[$I][3]
        Case "Enroll"
            $Return = _ArraySearch($Array, $Array[$I][0], 0, $I - 1, 0, 0, 0, 0)
            If $Return > 0 Then
                If $Array[$Return][1] = $Array[$I][1] Then
                    _ArrayDelete($Array, $I)
                    $Array[$Return][3] = ""
                    ConsoleWrite("MOVE" & @CRLF)
                    ;Do move
                Else
                    ;Do Enroll
                    ConsoleWrite("ENROLL" & @CRLF)
                EndIf
            Else
                ;Do Enroll
                ConsoleWrite("ENROLL" & @CRLF)
            EndIf
        Case "Withdraw"
            $Return = _ArraySearch($Array, $Array[$I][0], 0, $I - 1, 0, 0, 0, 0)
            If $Return > 0 Then
                If $Array[$Return][1] = $Array[$I][1] Then
                    _ArrayDelete($Array, $I)
                    $Array[$Return][3] = ""
                    ConsoleWrite("MOVE" & @CRLF)
                    ;Do move
                Else
                    ;Do Withdraw
                    ConsoleWrite("WITHDRAW" & @CRLF)
                EndIf
            Else
                ;Do Withdraw
                ConsoleWrite("WITHDRAW" & @CRLF)
            EndIf
    EndSwitch
Next

If you run this from SciTE, it will display:

MOVE

ENROLL

WITHDRAW

ENROLL

It loops through your names backwards, which is why it shows it the way it does.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

BrewMan, I keep trying to use your code for my own testing but I'm getting dimensional errors with the arrays. I can't tell but have you hard coded the size of the array somewhere? Here is my test code:

#include <Array.au3>


Local $Array[4][6] = [["FirstName", "LastName", "IDNumber", "Location", "Grade", "Action"], ["john", "smith", "111222", "Denver", "2", "enroll"], ["jack", "jones", "333444", "denver", "4", "withdraw"], ["jack", "jones", "333444", "lasvegas", "4", "enroll"]]

;Global $Array[5][4] = [["Bob", "Smith", "Denver", "Enroll"],["John", "Jones", "Denver", "Withdraw"],["Jacob", "Jackson", "Denver", "Withdraw"],["Mike", "Thomas", "Denver", "Enroll"],["John", "Jones", "LasVegas", "Enroll"]]

For $I = 5 To 0 Step -1
    Switch $Array[$I][6]
        Case "Enroll"
            $Return = _ArraySearch($Array, $Array[$I][0], 0, $I - 1, 0, 0, 0, 0)
            If $Return > 0 Then
                If $Array[$Return][1] = $Array[$I][1] Then
                    _ArrayDelete($Array, $I)
                    $Array[$Return][3] = ""
                    ConsoleWrite("MOVE" & @CRLF)
                    ;Do move
                Else
                    ;Do Enroll
                    ConsoleWrite("ENROLL" & @CRLF)
                EndIf
            Else
                ;Do Enroll
                ConsoleWrite("ENROLL" & @CRLF)
            EndIf
        Case "Withdraw"
            $Return = _ArraySearch($Array, $Array[$I][0], 0, $I - 1, 0, 0, 0, 0)
            If $Return > 0 Then
                If $Array[$Return][1] = $Array[$I][1] Then
                    _ArrayDelete($Array, $I)
                    $Array[$Return][3] = ""
                    ConsoleWrite("MOVE" & @CRLF)
                    ;Do move
                Else
                    ;Do Withdraw
                    ConsoleWrite("WITHDRAW" & @CRLF)
                EndIf
            Else
                ;Do Withdraw
                ConsoleWrite("WITHDRAW" & @CRLF)
            EndIf
    EndSwitch
Next

Share this post


Link to post
Share on other sites

Did you even LOOK at the code I posted before you added it to yours? Of course I hard coded the arrays, it was an example of a way to do it, not a stand alone function. My array was dimensioned with 5 rows, 4 columns, because that was what you gave us to work with, you added another column which is going to make my example useless unless you understand what it's doing first. Try running the code I gave you, as it is, and see what I did in it before trying to Frankestein it.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#10 ·  Posted

I did look at the code. And it works for your example. But I don't know where you're hard coding the dimensions since the code doesn't have any comments. Plus the arrays im working with in the real script are dynamic. They will always be the same number of columns, but dynamic rows. Thats why I don't usually like to read arrays backwards because I never know how big or small they will be.

Share this post


Link to post
Share on other sites

#11 ·  Posted

One approach I have taken for this type of thing is associative arrays. You will find a nice UDF in the forums for this. Effectively, you create associative arrays and even if the person is in the list twice, only one entry is created: x($username & '.enrolledstatus','True')

I didnt do an algorithm here, but check this forum for details.

You can then directly address them x('Bob.enrolledstatus')

BTW, I have used this for several thousands of records and it performs quite well.

Share this post


Link to post
Share on other sites

#12 ·  Posted

Here's another go at this taking into account that the array can have more or less rows every time you try this. Also as long as the second dimension doesn't change the column count it should work.

#include <Array.au3>
Local $Array[4][6] = [["FirstName", "LastName", "IDNumber", "Location", "Grade", "Action"], ["john", "smith", "111222", "Denver", "2", "enroll"], ["jack", "jones", "333444", "denver", "4", "withdraw"], ["jack", "jones", "333444", "lasvegas", "4", "enroll"]]
_ArrayDisplay($Array)

For $I = UBound($Array) - 1 To 0 Step -1 ;Loop backwards through the array, the end of the array is determined by the Ubound function
    Switch $Array[$I][5] ; Checks to see if you're Enrolling or Withdrawing each name
        Case "Enroll" ; if enroll use this section
            $Return = _ArraySearch($Array, $Array[$I][0], 0, $I - 1, 0, 0, 0, 0) ;Checks to see if there is a duplicate first name in the list
            If $Return > 0 Then
                If $Array[$Return][1] = $Array[$I][1] Then ; if there is a duplicate first name, check that person's last name to see if it matches
                    _ArrayDelete($Array, $I) ; if it matches, delete the current user's row from the array
                    $Array[$Return][5] = "" ; blank out the matching user's action entry
                    ConsoleWrite("MOVE" & @CRLF)
                    ;Do move
                Else ; if first and last name doesn't match, do the enroll function
                    ;Do Enroll
                    ConsoleWrite("ENROLL" & @CRLF)
                EndIf
            Else ; if first name doesn't match, do the enroll funtions
                ;Do Enroll
                ConsoleWrite("ENROLL" & @CRLF)
            EndIf
        Case "Withdraw" ; see the enroll section for what i'm doing in this section, as it's exactly the same.
            $Return = _ArraySearch($Array, $Array[$I][0], 0, $I - 1, 0, 0, 0, 0)
            If $Return > 0 Then
                If $Array[$Return][1] = $Array[$I][1] Then
                    _ArrayDelete($Array, $I)
                    $Array[$Return][5] = ""
                    ConsoleWrite("MOVE" & @CRLF)
                    ;Do move
                Else
                    ;Do Withdraw
                    ConsoleWrite("WITHDRAW" & @CRLF)
                EndIf
            Else
                ;Do Withdraw
                ConsoleWrite("WITHDRAW" & @CRLF)
            EndIf
    EndSwitch
Next
_ArrayDisplay($Array))

I would suggest taking a look at what I'm doing in this script before you try and implement it into something else. I've included comments in the script so that you can see what's happening.

NOTE: The reason I blank out the matching user's "Action" column entry is so that it will not match either Withdraw or Enroll so nothing will happen when the script reaches that user again because it has already done the move operation.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

BrewMan, here is my full code. I think I've gotten what you're doing. My only problem is that when running the code I get an output of:

enroll

withdraw

enroll

when I should be getting an output of

enroll

withdraw

As you can see I've changed the check to compare against the ID number because there will never be a chance of duplicates. So if a single ID number appears twice that is a 99% sure fire check to say the condition should be a move. I don't like comparing names because we have several people with the same name.

#NoTrayIcon
#include <Array.au3>
#include <AD.au3>

; Global variables
Global $iRowStart = 1 ; starting row, 0=no header row, 1=header row
Global $bError, $bValid, $sErrorMsg

Local $aRaw[4][6] = [["FirstName", "LastName", "IDNumber", "Location", "Grade", "Action"], ["john", "smith", "111222", "Denver", "2", "enroll"], ["jack", "jones", "333444", "denver", "4", "withdraw"], ["jack", "jones", "333444", "lasvegas", "4", "enroll"]]
_ArrayDisplay($aRaw)

;_AD_Open() ; open connection to active directory

_ValidateData($aRaw)
If $bValid = True Then _Broker($aRaw)

;_AD_Close() ; close connection to active directory

Func _Broker($aInput)
    ;For $i = 1 to UBound($aInput) - 1 ; change $i to 1 if $aInput contains a header row
    For $i = UBound($aInput) - 1 To $iRowStart Step -1
        ;_GetUsername()
        ;_DoesUserExist($sUsername)
        ;If $bUserExists = True Then
            Switch $aInput[$i][5]
                Case "enroll"
                    $iReturn = _ArraySearch($aInput, $aInput[$i][2], 0, $i - 1, 0, 0, 0, 0)
                    If $iReturn > 0 Then
                        If $aInput[$iReturn][2] = $aInput[$i][2] Then
                            _ArrayDelete($aInput, $i)
                            $aInput[$iReturn][5] = ""
                            ConsoleWrite("move" & @CR)
                        Else
                            ConsoleWrite("enroll" & @CR)
                        EndIf
                    Else
                        consolewrite("enroll" & @CR)
                    EndIf
                Case "withdraw"
                    $iReturn = _ArraySearch($aInput, $aInput[$i][2], 0, $i - 1, 0, 0, 0, 0)
                    If $iReturn > 0 Then
                        If $aInput[$iReturn][2] = $aInput[$i][2] Then
                            _ArrayDelete($aInput, $i)
                            $aInput[$iReturn][5] = ""
                            ConsoleWrite("move" & @CR)
                        Else
                            ConsoleWrite("withdraw" & @CR)
                        EndIf
                    Else
                        consolewrite("withdraw" & @CR)
                    EndIf
            EndSwitch
    Next
EndFunc   ;==>_Broker

Func _ValidateData($aInput)
    $bValid = False
    $bError = False
    For $i = $iRowStart To UBound($aInput) - 1
        For $n = 0 to UBound($aInput, 2) - 1
            If $aInput[$i][$n] = "" Then
                $bError = True
                $sErrorMsg &= "Array contains null data" & @CR
                ExitLoop
            Else
                $bValid = True
            EndIf
        Next
    Next
EndFunc   ;==>_ValidateData
Edited by kor

Share this post


Link to post
Share on other sites

#14 ·  Posted

Change these lines:

$iReturn = _ArraySearch($aInput, $aInput[$i][2], 0, $i - 1, 0, 0, 0, 0)
                    If $iReturn > 0 Then
                        If $aInput[$iReturn][2] = $aInput[$i][2] Then

To this

$iReturn = _ArraySearch($aInput, $aInput[$i][0], 0, $i - 1, 0, 0, 0, 0); First name
                    If $iReturn > 0 Then
                        If $aInput[$iReturn][2] = $aInput[$i][1] Then ; Last name

You're supposed to be searching the user names for matches, they are held in the array in the 0 and 1 positions for first and last names. The #2 subitems are the ID numbers, if you wanted to search on the ID numbers you should have stated that 12 posts ago when you started this topic, not to mention you probably should have included the ID numbers in the original post so that I could have suggested another way of doing this.

If you continue to change the parameters of what it is you're searching, and what you're searching for, no wonder the code being supplied to you doesn't work. You need to read the help file and see what each and every one of these commands does and learn that before trying to just cut and paste this into something and change it. If you don't know how it works in the first place, you'll be totally lost when you try to alter it.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

How would you do it totally differently if you are checking ID numbers instead of names? I dont see why the code would be so fundamentally different just because your checking 1 value over another.

And I have looked at the helpfile. Although the only thing your doing that I didnt initially get was the array search. Everything else your doing is just If then statements and an Array delete based on the index of the return.

EDIT:

also, making your changes I'm still getting the wrong output of:

enroll

withdraw

enroll

EDIT2:

The code from your post#12 also does not return the correct output. It returns:

MOVE

MOVE

when it should return

Enroll

Move

Edited by kor

Share this post


Link to post
Share on other sites

#16 ·  Posted

I forgot that I was using a modified _ArraySearch because the included one that comes with AutoIt isn't very good when searching through an array backwards. I will see if there's a work around for the _arraysearch function as it's written.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#17 ·  Posted

I think I've got it. Please look over and tell me what you think. What I tried changing was the $iReturn check because technically the check would also be true since every time you searched the value would be greater than zero even for entries that were only present once. What I did was say if you are greater than zero but less than $i (since it looks at the array backwards)

#include <Array.au3>
$iRowStart = 1
Local $aInput[4][6] = [["FirstName", "LastName", "IDNumber", "Location", "Grade", "Action"], ["john", "smith", "111222", "Denver", "2", "enroll"], ["jack", "jones", "333444", "denver", "4", "withdraw"], ["jack", "jones", "333444", "lasvegas", "4", "enroll"]]
_ArrayDisplay($aInput)

For $i = UBound($aInput) - 1 To $iRowStart Step -1
    Switch $aInput[$i][5]
        Case "enroll"
            $iReturn = _ArraySearch($aInput, $aInput[$i][2])
            If $iReturn > 0 And $iReturn < $i Then
                If $aInput[$iReturn][2] = $aInput[$i][2] Then
                    consolewrite("move " & $aInput[$i][0] & @CR)
                    _ArrayDelete($aInput, $i)
                    $aInput[$iReturn][5] = ""
                Else
                    consolewrite("enroll " & $aInput[$i][0] & @CR)
                EndIf
                Else
                    consolewrite("enroll " & $aInput[$i][0] & @CR)
                EndIf
        Case "withdraw"
            $iReturn = _ArraySearch($aInput, $aInput[$i][2])
            If $iReturn > 0 And $iReturn < $i Then
                If $aInput[$iReturn][2] = $aInput[$i][2] Then
                    consolewrite("move " & $aInput[$i][0] & @CR)
                    _ArrayDelete($aInput, $i)
                    $aInput[$iReturn][5] = ""
                Else
                    consolewrite("withdraw " & $aInput[$i][0] & @CR)
                EndIf
            Else
                consolewrite("withdraw " & $aInput[$i][0] & @CR)
            EndIf
    EndSwitch
Next

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