# 2D arrays compare with details - yet another solution

## Recommended Posts

i needed to compare two 2D arrays, and produce specific results: which cell holds different values, and what are the different values.

tolf has a nice UDF for 2D array management (it does need some updating for newer versions of AutoIt)

'?do=embed' frameborder='0' data-embedContent>>

his function _Array2D_ToString() can be used to convert arrays to strings and compare the strings, which is fine if you need Boolean answer to the question "are the arrays identical".

there are other approaches, as demonstrated by BugFix here, for strings and 1D arrays:

'?do=embed' frameborder='0' data-embedContent>>

after some tries (and errors), i finally came up with this function. features:

- it always returns an array, so no _IsArray() or @error needs to be checked after return

- it exits elegantly for accidental input that is not 2D array, so this needs not be checked prior to call

- it can be used for Boolean answer

in the function header comment, you may want to read the "Return value" and "Remarks" parts carefully.

```; #FUNCTION# ====================================================================================================================
; Name ..........: _Array_Compare2D
; Description ...: Compares the first two diemnsions of two input arrays.
; Syntax.........: _Array_Compare2D(\$a1,\$a2)
; Parameters ....: \$a1,\$a2 - two 2D arrays.
; Return values .: An array of size [n+1][3], where n is the number of differences, and the columns are:
;                  rows 1..n:
;                    cell position (zero-based) | value in \$a1 | value in \$a2
;                  row 0:
;                    cell [0][0] holds the number of differences, 0 means no differences, -1 means some mismatch between the arrays sizes or dimensions.
;                    cell [0][1] holds the sizes of dimensions of \$a1 (only 1st two dimentions)
;                    cell [0][2] holds the sizes of dimensions of \$a2 (only 1st two dimentions)
;                  an array is always returned, even when an error occurs - see "Remarks" section hereunder.
; Author ........: orbs
; Modified ......:
; Remarks .......: input variables, 1D arrays, or arrays different in sizes, are handled as described in the "Return values" section above, also see Exmple #2 hereunder
;                  to use this function as boolean indication (arrays are either identical or not), check cell [0][0] of the return array:
;                    arrays are identical only when cell [0][0] holds 0.
;                  Example #1: in case the arrays are of size 8x7 and are identical except of:
;                    \$a1[3][1]='ABC' and \$a2[3][1]='DEF'
;                    \$a1[5][6]='123' and \$a2[5][6]='456'
;                  the return array will be:
;                    +---+---+---+
;                    | 2 |8x7|8x7|
;                    +---+---+---+
;                    |3x1|ABC|DEF|
;                    +---+---+---+
;                    |5x6|123|456|
;                    +---+---+---+
;                  Example #2: in case the arrays sizes are different: \$a1 size = 3x2 , \$a2 size = 1x2
;                  the return array will be:
;                    +---+---+---+
;                    | -1|3x2|1x2|
;                    +---+---+---+
;                  note: 1D array of size 3 will be noted as 3x0, a variable will be noted as an array of size 0x0
; Related .......:
; Example .......:
; ===============================================================================================================================
Func _Array_Compare2D(\$a1,\$a2)
; declare
Dim \$a3[1][3]   ; will be filled and returned
Local \$n=0      ; the number of differences
Local \$i,\$j     ; loop index variables
; init
\$a3[0][0]=0
\$a3[0][1]=UBound(\$a1,1)&'x'&UBound(\$a1,2)
\$a3[0][2]=UBound(\$a2,1)&'x'&UBound(\$a2,2)
; precheck sizes and dimensions
If UBound(\$a1,2)=0 Or _                 ; \$a1 is 1D array
UBound(\$a2,2)=0 Or _                ; \$a2 is 1D array
UBound(\$a1,3)>0 Or _                ; \$a1 is 3D array or more
UBound(\$a2,3)>0 Or _                ; \$a2 is 3D array or more
UBound(\$a1,1)<>UBound(\$a2,1) Or _   ; size of 1st dimension is different
UBound(\$a1,2)<>UBound(\$a2,2) Then   ; size of 2nd dimension is different
\$a3[0][0]=-1
Return \$a3
EndIf
; compare
For \$i=0 To UBound(\$a1,1)-1
For \$j=0 To UBound(\$a1,2)-1
If \$a1[\$i][\$j]<>\$a2[\$i][\$j] Then
\$n+=1
ReDim \$a3[\$n+1][3]
\$a3[0][0]=\$n
\$a3[\$n][0]=\$i&'x'&\$j
\$a3[\$n][1]=\$a1[\$i][\$j]
\$a3[\$n][2]=\$a2[\$i][\$j]
EndIf
Next
Next
; return
Return \$a3
EndFunc   ;==>_Array_Compare2D```

here is an example script. note that the #include is not required for the function, only for _ArrayDisplay()

```#include <Array.au3>
Dim \$a1[8][7]
Dim \$a2[8][7]
\$a1[3][1]='ABC'
\$a2[3][1]='DEF'
\$a1[5][6]='123'
\$a2[5][6]='456'
\$a3=_Array_Compare2D(\$a1,\$a2)
_ArrayDisplay(\$a3)```
` `

this is how the output looks like:

hope it will help someone in the future.

Edited by orbs

##### Share on other sites

- it always returns an array, so no _IsArray() or @error needs to be checked after return

I think you mean IsArray and just use UBound as IsArray is practically pointless.

##### Share on other sites

IsArray() pointless? if your script assumes you have an array, but it's not - and many functions that are supposed to return an array, return 0 upon error - then by next call to the assumed array, your code crash. happened to me more than once, for example with _FileListToArray(), when no files found (which is definitely not an error, but a legitimate result).

##### Share on other sites

As I said, use UBound instead.

```#include <Constants.au3>

Local \$sString = ''
If UBound(\$sString) Then
MsgBox(\$MB_SYSTEMMODAL, '', 'Is an array.')
Else
MsgBox(\$MB_SYSTEMMODAL, '', 'Is not an array.')
EndIf

Local \$aArray[1] = [0]
If UBound(\$aArray) Then
MsgBox(\$MB_SYSTEMMODAL, '', 'Is an array.')
Else
MsgBox(\$MB_SYSTEMMODAL, '', 'Is not an array.')
EndIf```

##### Share on other sites

As I said, use UBound instead.

Why would you use Ubound in place of IsArray? Please elaborate.

Edited by czardas

##### Share on other sites

Because most times I need UBound to find the size of the array, so it's one less call to make.

##### Share on other sites

Because most times I need UBound to find the size of the array, so it's one less call to make.

I thought that might be the case. Both keys fit the same lock. In fact there's very little in it other than a miniscule time lag with Ubound, which is to be expected.

```Local \$a[1], \$test, \$iTimer

\$iTimer = TimerInit()
For \$i = 1 To 10000000
\$test = IsArray(\$a)
Next
ConsoleWrite(TimerDiff(\$iTimer)  & @LF)

\$iTimer = TimerInit()
For \$i = 1 To 10000000
\$test = UBound(\$a)
Next
ConsoleWrite(TimerDiff(\$iTimer)  & @LF)```
Edited by czardas

##### Share on other sites

it's not about time, it's about code that can be avoided if not needed. "Both keys fit the same lock": what i tried to do is to have no lock at all to waste code on...  to my view, as a concept, if a function is supposed to return an array - then an array will be returned. even if an error occurred, the function can set @error, but nothing should stop it from returning an empty array. it's like having a computational function that returns the result string "i could not compute your request" upon error. to me, it makes no sense. it forces the calling script to perform a checkup on the return value type, instead of focusing on processing the value. now, i'm all for robustness, but if a checkup can be safely avoided, i'd avoid it.

for example, see the example script i attached - it makes no checkup on @error or on the return value type, as you can see, it goes straight to _ArrayDisplay. if i needed a checkup, the script will be:

\$a3=_Array_Compare2D(\$a1,\$a2)

if not @error then

_ArrayDisplay(\$a3)

else

; do something

endif

now, if i can avoid the IF...THEN...ELSE then i'd avoid it. that's all. too many lines of code are wasted on checkup, i'd avoid what i safely can.

Edit: also, thanks for anyone who moved the thread to this forum, i was not sure what is the right place for it.

Edited by orbs

##### Share on other sites

This might be a bit faster on large arrays.

```; #FUNCTION# ====================================================================================================================
; Name ..........: _Array_Compare2D
; Description ...: Compares the first two diemnsions of two input arrays.
; Syntax.........: _Array_Compare2D(\$a1,\$a2)
; Parameters ....: \$a1,\$a2 - two 2D arrays.
; Return values .: An array of size [n+1][3], where n is the number of differences, and the columns are:
;                  rows 1..n:
;                    cell position (zero-based) | value in \$a1 | value in \$a2
;                  row 0:
;                    cell [0][0] holds the number of differences, 0 means no differences, -1 means some mismatch between the arrays sizes or dimensions.
;                    cell [0][1] holds the sizes of dimensions of \$a1 (only 1st two dimentions)
;                    cell [0][2] holds the sizes of dimensions of \$a2 (only 1st two dimentions)
;                  an array is always returned, even when an error occurs - see "Remarks" section hereunder.
; Author ........: orbs
; Modified ......:
; Remarks .......: input variables, 1D arrays, or arrays different in sizes, are handled as described in the "Return values" section above, also see Exmple #2 hereunder
;                  to use this function as boolean indication (arrays are either identical or not), check cell [0][0] of the return array:
;                    arrays are identical only when cell [0][0] holds 0.
;                  Example #1: in case the arrays are of size 8x7 and are identical except of:
;                    \$a1[3][1]='ABC' and \$a2[3][1]='DEF'
;                    \$a1[5][6]='123' and \$a2[5][6]='456'
;                  the return array will be:
;                    +---+---+---+
;                    | 2 |8x7|8x7|
;                    +---+---+---+
;                    |3x1|ABC|DEF|
;                    +---+---+---+
;                    |5x6|123|456|
;                    +---+---+---+
;                  Example #2: in case the arrays sizes are different: \$a1 size = 3x2 , \$a2 size = 1x2
;                  the return array will be:
;                    +---+---+---+
;                    | -1|3x2|1x2|
;                    +---+---+---+
;                  note: 1D array of size 3 will be noted as 3x0, a variable will be noted as an array of size 0x0
; Related .......:
; Example .......:
; ===============================================================================================================================
Func _Array_Compare2D(\$a1, \$a2)
; declare
Local \$a3[1][3] ; will be filled and returned <<<<<<<<<<< Don't use Dim
Local \$n = 0 ; the number of differences
Local \$i, \$j ; loop index variables
; init
\$a3[0][0] = 0
\$a3[0][1] = UBound(\$a1, 1) & 'x' & UBound(\$a1, 2)
\$a3[0][2] = UBound(\$a2, 1) & 'x' & UBound(\$a2, 2)
; precheck sizes and dimensions
;~  If UBound(\$a1, 2) = 0 Or _                 ; \$a1 is 1D array
;~          UBound(\$a2, 2) = 0 Or _                ; \$a2 is 1D array
;~          UBound(\$a1, 3) > 0 Or _                ; \$a1 is 3D array or more
;~          UBound(\$a2, 3) > 0 Or _                ; \$a2 is 3D array or more
;~          UBound(\$a1, 1) <> UBound(\$a2, 1) Or _   ; size of 1st dimension is different
;~          UBound(\$a1, 2) <> UBound(\$a2, 2) Then ; size of 2nd dimension is different
;~      \$a3[0][0] = -1
;~      Return \$a3
;~  EndIf
If UBound(\$a1, 0) <> 2 Or (Ubound(\$a1, 1) <> Ubound(\$a2, 1)) Or (Ubound(\$a1, 2) <> Ubound(\$a2, 2)) Then
\$a3[0][0] = -1
Else
; compare
For \$i = 0 To UBound(\$a1, 1) - 1
For \$j = 0 To UBound(\$a1, 2) - 1
If \$a1[\$i][\$j] <> \$a2[\$i][\$j] Then
\$n += 1
If \$n = > UBound(\$a3, 1) Then ReDim \$a3[\$n + 1000][3] ; Don't ReDim so often, large arrays would seriously slow this down otherwise
\$a3[0][0] = \$n
\$a3[\$n][0] = \$i & 'x' & \$j
\$a3[\$n][1] = \$a1[\$i][\$j]
\$a3[\$n][2] = \$a2[\$i][\$j]
EndIf
Next
Next
ReDim \$a3[\$n][3]
EndIf
; return
Return \$a3
EndFunc   ;==>_Array_Compare2D```
It avoids using ReDim every time you don't find a match. It also streamlines the bounds checking, so that if the arrays have more or less dimensions than 2 or they don't have the same size dimensions, it sets the error condition.

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

heaven on earth! does Ubound(\$a,0) give me the number of dimensions of \$a? i was looking for that! but i used Ubound(\$a,3)>0 as a condition for that there are more dimensions than 2.

thanks for the optimization suggestion, i will certainly implement it.

also, why is the Else needed at the precheck phase? i hope it's just for code structuring, because i can safely return if the precheck fails.

##### Share on other sites

heaven on earth! does Ubound(\$a,0)

The example is not clear in the current version of the help file.

```#include <Array.au3> ; Required for _ArrayDisplay.
#include <Constants.au3>

Example()

Func Example()
Local \$aArray[10][20]
Local \$iRows = UBound(\$aArray, 1) ; Total number of rows. In this example it will be 10.
Local \$iCols = UBound(\$aArray, 2) ; Total number of columns. In this example it will be 20.
Local \$iDimension = UBound(\$aArray, 0) ; The dimension of the array e.g. 1/2/3 dimensional.

MsgBox(\$MB_SYSTEMMODAL, "", "The array is a " & \$iDimension & " dimensional array with " & _
\$iRows & " row(s) & " & \$iCols & " column(s).")

; Fill the array with data.
For \$i = 0 To \$iRows - 1
For \$j = 0 To \$iCols - 1
\$aArray[\$i][\$j] = "Row: " & \$i & " - Col: " & \$j
Next
Next
_ArrayDisplay(\$aArray)
EndFunc   ;==>Example```

##### Share on other sites

it's not about time, it's about code that can be avoided if not needed. "Both keys fit the same lock": what i tried to do is to have no lock at all to waste code on...to my view, as a concept, if a function is supposed to return an array - then an array will be returned. even if an error occurred, the function can set @error, but nothing should stop it from returning an empty array.

My comments were general - not specific to your example. The error return value of a function does not have to be the same data type as that requested. For example: I can't imagine why you would want to return an empty 10 dimensional array if an error occurs. Zero is generally a good error return value except perhaps in cases where zero is a valid result.

Edited by czardas

##### Share on other sites

it's not about time, it's about code that can be avoided if not needed. "Both keys fit the same lock": what i tried to do is to have no lock at all to waste code on...  to my view, as a concept, if a function is supposed to return an array - then an array will be returned. even if an error occurred, the function can set @error, but nothing should stop it from returning an empty array. it's like having a computational function that returns the result string "i could not compute your request" upon error. to me, it makes no sense. it forces the calling script to perform a checkup on the return value type, instead of focusing on processing the value. now, i'm all for robustness, but if a checkup can be safely avoided, i'd avoid it.

But don't you still have to check if the value returned has anything in it? I don't see the benefit of returning an empty array if you still have to check whether the array is empty or not. The only thing you're not doing is making it not check whether it's an array or not.

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

@czardas: "I can't imagine why you would want to return an empty 10 dimensional array if an error occurs" - occurrences when the return value must be very large when an error occurs are the exceptional, if exist at all. the point is that if the calling script expects an array, then that's what it will get, but the array can be very small (1x3 in size), as long as it is an array.

@BrewManNH: "But don't you still have to check if the value returned has anything in it?" - no, i don't need to check. see the example. i'm not checking anything, i'm just accessing the data. i'm asking "what is the data?" instead of asking "is the data ok?" and then "if so, what is the data?". that's one question instead of two.

anyway, i must agree that it all is a matter of specific usage. some uses may be optimized by this way or the other. it's also a matter of style, and that's mine - i want to get what i expect to get. "no alarms and no surprises please." - and no error checks if can be avoided. and since the source is open, everyone are encouraged to modify it to their own preferences.

##### Share on other sites

BTW, one thing I also noticed is that the comparison isn't case sensitive, so ABC is the same as abC for this script. If you want a case sensitive comparison, you need to use "If Not(\$a1[\$i][\$j]==\$a2[\$i][\$j]) Then" instead of "If \$a1[\$i][\$j]<>\$a2[\$i][\$j] Then"

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

orbs,

The one advantage from posting in the Examples section is you learn a lot more about AutoIt. I don't code like I used to 2 years ago.

##### Share on other sites

@czardas: "I can't imagine why you would want to return an empty 10 dimensional array if an error occurs" - occurrences when the return value must be very large when an error occurs are the exceptional, if exist at all. the point is that if the calling script expects an array, then that's what it will get, but the array can be very small (1x3 in size), as long as it is an array.

It's nice to have the option to return any type of value. Returning an expected data type with an error can sometimes lead to confusion. Unless you plan on filling the empty array which you returned with data, there is no point in returning it. Checking to see if all the elements of a multidimensional array are empty is unecessary processing when you are not intending to use the the array at the end of the day - which is what BrewManNH was saying.

Edited by czardas

##### Share on other sites

Strictly speaking, an empty array is not at all obvious to build with AutoIt alone. AFAIK only [some?] objects may return empty arrays. In this case IsArray is True but dimensions are 0. There has been a thread about this, with trancexx posting there.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

## Create an account

Register a new account

×

• Wiki

• Back

• #### Beta

• Git
• FAQ
• Our Picks
×
• Create New...