Jump to content
Sign in to follow this  
NDog

[Solved] - Compare multiple arrays

Recommended Posts

NDog

I need help with comparing arrays. It is a two part question.

QUESTION 1

$array1 contains unique values, (eg same value cannot repeat twice). $array1 does not change

$array2 contains only values from $array1, but these can be repeated. $array2 grows larger.

example ($array2 does not contain all the elements of $array1 yet, continue)

$array1 = {1,2,3,4,A,B,C,D}

$array2 = {A,B,3,4,A,A}

What I want to happen is as soon as all the values in $array2 match $array1, then I want it to perform a function

example ($array2 contains all the elements of $array1. do something)

$array1 = {1,2,3,4,A,B,C,D}

$array2 = {A,B,3,4,A,A,1,1,2,C,D}

QUESTION 2

I am looping through $array1 and adding elements from $array1 to $array2.

How can I ensure that if an element from $array1 has already been assigned to $array2, not to add it to $array2 again

example

$array1 = {1,2,3,4,A,B,C,D}

$array2 = {2,A,B}

If while looping through $array1 if it matches "2" or "A" or "B" (from $array2), then don't add to the $array2 and continue to loop though till it gets a match eg "1" and add this to $array2 (and then perform a function related to "1"). I hope this makes sense.

Edited by NDog

Share this post


Link to post
Share on other sites
UEZ

Make array 2 unique and compare both arrays. If you wish you can sort both arrays to speed up array compare.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Robjong

Hi, here is one way how you could do it...

- Make the second array unique.

_ArrayUnique

- Check if the arrays are the same size, if they are not they can not be equal and we stop here.

UBound

- Sort second array.

_ArraySort

- Loop through the arrays and compare values.

For...To...Next

Edit: changed "both arrays" to "second array" as the first array does not change.

Edited by Robjong

Share this post


Link to post
Share on other sites
NDog

Here are some real values, where $users would be $array1 and $doneusers would be $array2, I haven't managed to find the solution yet but will experiment with _arrayunique

#Include <Array.au3>
Local $users[3][4]
$users[0][0]="bob"
$users[1][0]="mary"
$users[2][0]="janet"
$users[0][1]="bob is your uncle"
$users[1][1]="mary is your mother"
$users[2][1]="janet is friend"
$users[0][2]="fish"
$users[1][2]="meat"
$users[2][2]="chicken"
$users[0][3]="arizona"
$users[1][3]="kentucky"
$users[2][3]="kentucky"
Local $doneusers[5] = ["bob", "mary", "bob", "mary", "mary"]
_ArrayDisplay($users,"$users")
_ArrayDisplay($doneusers,"$doneusers")
Edited by NDog

Share this post


Link to post
Share on other sites
incepator

#include <Array.au3>

_ArrayUnique function....

_ArrayUnique($aArray [, $iDimension = 1 [, $iBase = 0 [, $iCase = 0 [, $vDelim = "|"]]]])

Autoit Help File...

Share this post


Link to post
Share on other sites
NDog

I have got the _ArrayUnique part working :) . I am just working on the last part

- Loop through the arrays and compare values.

For...To...Next

Just trying to figure what exactly I need to compare in order not to redo an already used value, this is related to question 2

For example

; determine if user has already been processed
For $i = 0 To UBound($users,1) - 1
  For $j = 1 To $doneusers[0] ; contains the amount of records
   ConsoleWrite("$users " & $i & ": " &$users[$i][$uname]&@CRLF)
   ConsoleWrite("$doneusers " & $j & ": " &$doneusers[$j]&@CRLF)
  Next
Next

What am I supposed to use to compare if a user has not already been processed? This is because I will run this loop from the beginning everytime, so I am confused.

I am really close, thanks for your advice so far

Edited by NDog

Share this post


Link to post
Share on other sites
UEZ

Try this:

#include <Array.au3>

#region question 1
Global $array1[8] = [1,2,3,4,"A","B","C","D"]
Global $array2[11] = ["A","B",3,4,"A","A",1,1,2,"C","D"]

$array2_unique = _ArrayUnique($array2)
_ArraySort($array2_unique, 0, 1)
$string1  = _ArrayToString($array1)
$string2 = _ArrayToString($array2_unique, "|", 1)

If $string1 = $string2 Then 
MsgBox(0, "Equal", "Action")
Else
MsgBox(0, "Not Equal", "No Go!")
EndIf
#endregion

#region question2
Global $array1[8] = [1,2,3,4,"A","B","C","D"]
Global $array2[3] = [2,"A","B"]
_ArrayConcatenate($array2, $array1)
$array2 = _ArrayUnique($array2)
_ArraySort($array2, 0, 1)
_ArrayDelete($array2, 0)
_ArrayDisplay($array2)
#endregion

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Robjong

Here is an example of what I had in mind...

#include <Array.au3>


Local $sSomeValueToAdd = "janet" ; some new value to add
Local $doneusers[5] = ["bob", "mary", "bob", "mary", "mary"]
Local $users[3][4]
$users[0][0] = "bob"
$users[1][0] = "mary"
$users[2][0] = "janet"

$users[0][1] = "bob is your uncle"
$users[1][1] = "mary is your mother"
$users[2][1] = "janet is friend"

$users[0][2] = "fish"
$users[1][2] = "meat"
$users[2][2] = "chicken"

$users[0][3] = "arizona"
$users[1][3] = "kentucky"
$users[2][3] = "kentucky"


; array1, this only has to be done once, as long as the $users array does not change
Local $array1 = _ArrayUnique($users, 1) ; 2D so we specify the dimension we need
_ArraySort($array1, 0, 1) ; sort array, start at 1 as 0 holds the total

; do this whenever $doneusers has changed, to make comparing easier
Local $array2 = _ArrayUnique($doneusers)
_ArraySort($array2, 0, 1) ; sort array, start at 1 as 0 holds the total

; view the arrays
;~ _ArrayDisplay($array1,"$array1")
;~ _ArrayDisplay($array2,"$array2")


#region - Check if the arrays are equal
Local $fEqual = False
If $array1[0] == $array2[0] Then ; arrays are of equal size, check if all values from array1 are present in array2
$fEqual = True
For $i = 1 To $array1[0] Step 1
If $array1[$i] <> $array2[$i] Then ; compare elements
$fEqual = False
ExitLoop
EndIf
Next
EndIf

If $fEqual Then ; the arrays are the same, do you need to do something with this information?
ConsoleWrite("-> ARRAYS ARE EQUAL" & @LF)
; ...
Else
ConsoleWrite("-> ARRAYS ARE NOT EQUAL" & @LF)
; ...
EndIf
#endregion - Check if the arrays are equal

#region - Check if some value already exists in the array
$sSomeValueToAdd = StringLower($sSomeValueToAdd) ; case insensetive compare so make the string lower case

Local $fExists = False
For $i = 1 To $array2[0] Step 1
If StringLower($array2[$i]) == $sSomeValueToAdd Then ; compare value and element
$fExists = True ; the values already exists
ExitLoop
EndIf
Next

If $fExists Then ; the value is not present in the array, do you need to do something with this information?
ConsoleWrite("-> VALUE """ & $sSomeValueToAdd & """ IS ALREADY PRESENT ARRAY2" & @LF)
; ...
Else
ConsoleWrite("-> VALUE """ & $sSomeValueToAdd & """ IS NOT PRESENT ARRAY2" & @LF)
_ArrayAdd($doneusers, $sSomeValueToAdd) ; add the value to the array ($doneusers = $array2)
; ...
EndIf

; view the array $doneusers
;~ $doneusers = _ArrayUnique($doneusers) ; is needed now but should not be if you do it right?!
_ArrayDisplay($doneusers, "$doneusers")
#endregion - Check if some value already exists in the array

Share this post


Link to post
Share on other sites
NDog

Thanks UEZ and Robjong for your suggestions.

I wasn't able to figure out how to use region 2 in UEZ example in a usable way, eg in a loop, but the region 1 makes sense and I am using it.

As for question 2 it is not answered.

I have two arrays

$users, contains all users, eg bob, janet, mary, helen, grant

$doneusers, contains users that have been done, bob, grant

How can I make a loop that scans through $users and finds matches that have do not exist in $doneusers, and then do something, afterwards adding themselves to $doneusers, and then repeating the process until all the $users end up in $doneusers, and then doing something else?

This is the best I can do, but I am stuck

#include <Array.au3>

Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[2] = ["bob", "grant"]

;~ _ArrayDisplay($users, "$users")
;~ _ArrayDisplay($doneusers, "$doneusers")

SetupNextLogin()

Func SetupNextLogin()
; don't process already processed users
; $fExists 0 = not initialised
; $fExists 1 = no match found
; $fExists 2 = match was found

Local $fExists = 0
For $i = 0 To UBound($users,1) - 1
For $j = 0 To UBound($doneusers,1) - 1
ConsoleWrite("$users " & $i & ": " &$users[$i]&@CRLF)
ConsoleWrite("$doneusers " & $j & ": " &$doneusers[$j]&@CRLF)
ConsoleWrite("====="&@CRLF)

If $users[$i] <> $doneusers[$j] Then
$fExists = 1
EndIf

If $users[$i] = $doneusers[$j] Then
$fExists = 2
EndIf

Next
Next

Select
Case $fExists = 0
ConsoleWrite("~~~0 - Loop user~~~ "&@CRLF)
Case $fExists = 1
ConsoleWrite("~~~1 - Loop user~~~ "&@CRLF)
Case $fExists = 2
ConsoleWrite("~~~2 - Loop user~~~ "&@CRLF)
EndSelect

EndFunc

;~ _ArrayDisplay($users, "$users")
;~ _ArrayDisplay($doneusers, "$doneusers")
Edited by NDog

Share this post


Link to post
Share on other sites
Spiff59

Use a flag that you clear before the inner loop, set inside the inner loop, and test after the inner loop.

Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[2] = ["bob", "grant"]
Global $found

; determine if user has already been processed
For $i = 0 To UBound($users,1) - 1
    $found = 0
    For $j = 0 To UBound($doneusers,1) - 1
        If $doneusers[$j] = $users[$i] Then
            $found = 1
            ExitLoop
        EndIf
    Next
    If $found = 1 Then
        MsgBox(0,"",$users[$i] & " found")
    Else
        MsgBox(0,"",$users[$i] & " not found")
    EndIf
Next

Share this post


Link to post
Share on other sites
NDog

Thanks for your input Spiff59 but I am not trying to determine if a user is found or not. I am trying to determine if the user is only not found and then add another $user to $doneusers (eg add mary to $doneusers). Leave the loop entirely, do A. If all is equal then do B.

The reason for this is because the script actually exits once it cant find a user (does A) and saves its variables to a text file. The next time the script is run it gets the variables from the text file and repeats the process until it does B.

I hope this makes sense.

Eg

script.exe - first time
Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[1]
.. Noone has been processed, do something for bob
FileWrite("doneusers.txt, "bob" & @CRLF)
Exit

script.exe - second time
Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[1] = ["bob"]
.. bob has already been processed, do something for janet
FileWrite("doneusers.txt, "janet" & @CRLF)
Exit

script.exe - third time
Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[2] = ["bob", "janet"]
.. bob and janet have already been processed, do something for mary
FileWrite("doneusers.txt, "mary" & @CRLF)
Exit

script.exe - fourth time
Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[3] = ["bob", "janet", "mary"]
.. bob, janet and mary have already been processed, do something for helen
FileWrite("doneusers.txt, "helen" & @CRLF)
Exit

script.exe - fifth time
Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[4] = ["bob", "janet", "mary", "helen"]
.. bob, janet, mary and helen have already been processed, do something for grant
FileWrite("doneusers.txt, "grant" & @CRLF)
Exit

script.exe - sixth time
Global $users[5] = ["bob", "janet", "mary", "helen", "grant"]
Global $doneusers[5] = ["bob", "janet", "mary", "helen", "grant"]
.. bob, janet, mary, helen and grant have all been processed. All done!
FileDelete("doneusers.txt')
Exit
Edited by NDog

Share this post


Link to post
Share on other sites
NDog

I have solved this problem. It may not be as elegant as it could be. I decided to create a temporary array and populate it with all the users, then work through and blank each user from that array that had been processed.

; make a temporary array for $users
    Dim $tmpusers[1]
    For $i = 0 To UBound($users,1) - 1
        _ArrayAdd($tmpusers,$users[$i][$uname])
    Next
    _ArrayDelete($tmpusers,0)
;~     _ArraySort($tmpusers) ; must do this
;~     _ArrayDisplay($tmpusers,"$tmpusers")

    ; delete non matching users in $tmpusers array ((not doing this as it messes with the $i loop and cant be considered reliable))
    ; http://www.autoitscript.com/forum/topic/131736-ietablegetcollection-ietablewritetoarray-and-finally-arraydelete/
;~     _ArraySort($doneusers) ; must do this
;~     _ArrayDisplay($tmpusers,"$tmpusers")
;~     _ArrayDisplay($doneusers,"$doneusers")
    For $i = UBound($tmpusers,1) - 1 to 0 Step - 1 ; need to work backwards as the _arraydelete function below reduces the size of the array each time it is called
        For $j = 0 To UBound($doneusers,1) - 1
;~             ConsoleWrite("$tmpusers " & $i & ": " &$tmpusers[$i]&@CRLF)
;~             ConsoleWrite("$doneusers " & $j & ": " &$doneusers[$j]&@CRLF)
            If $tmpusers[$i] = $doneusers[$j] Then
;~                 ConsoleWrite("User being deleted from $tmpusers " & $i & ": " &$tmpusers[$i]&@CRLF)
;~                 _ArrayDelete($tmpusers, $i)
;~                 ConsoleWrite("User was deleted from $tmpusers " & $i & ": " &$tmpusers[$i]&@CRLF)
;~                 ConsoleWrite("User being blanked from $tmpusers " & $i & ": " &$tmpusers[$i]&@CRLF)
                $tmpusers[$i] = ""
            EndIf
        Next
    Next
;~     _ArrayDisplay($tmpusers,"$tmpusers")

    ; Debug, all values should match and these are non processed users
;~     For $i = 0 To UBound($users,1) - 1
;~         For $j = 0 To UBound($tmpusers,1) - 1
;~             If $users[$i][$uname] = $tmpusers[$j] Then
;~                 ConsoleWrite("$users " & $i & ": " &$users[$i][$uname]&@CRLF)
;~                 ConsoleWrite("$tmpusers " & $j & ": " &$tmpusers[$j]&@CRLF)
;~             EndIf
;~         Next
;~     Next

    ; Setup next user to be processed, set as $nextuser
    For $i = 0 To UBound($tmpusers,1) - 1
        If $tmpusers[$i] <> "" Then
            ConsoleWrite("$nextuser: " &$tmpusers[$i]&@CRLF)
            $nextuser = $tmpusers[$i]
            ExitLoop
        EndIf
    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  

×