# [Solved] - Compare multiple arrays

## Recommended Posts

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 on other sites

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

Br,

UEZ

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

##### Share on other sites

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 on other sites

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[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 on other sites

#include <Array.au3>

_ArrayUnique function....

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

Autoit Help File...

##### Share on other sites

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.

Edited by NDog

##### Share on other sites

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

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

##### Share on other sites

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

```#include <Array.au3>

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)
; ...
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 on other sites

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")

; 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 on other sites

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
EndIf
Next```

##### Share on other sites

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 on other sites

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
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```

## Create an account

Register a new account