D1Spartan Posted May 16, 2016 Share Posted May 16, 2016 I've done some searching, both in the forums and in the include files, and have not found a way to compare 2 arrays to check for equality. I have created a function (which I am willing to share if there is no way to do this currently), but I am wondering is there an existing function? The following code illustrates what I am trying to accomplish, but the results aren't correct expandcollapse popupDim $array1 [2][2] Dim $array2 [2][2] $value = 0 ; Populate Array For $i = 0 To 1 For $j = 0 To 1 $array1[$i][$j] = $value $value += 1 Next Next ; $array1 is equal to $array2 $array2 = $array1 ConsoleWrite ("Should be TRUE" & @CRLF) checkArray () ; Change the first value to 42 to make the two arrays not equal $array1[0][0] = 42 ConsoleWrite (@CRLF) ConsoleWrite ("Should be FALSE" & @CRLF) checkArray () Func checkArray () ; Check for equality using the standard (AutoIt) equality check If $array2 = $array1 Then ConsoleWrite ("Standard Check: True" & @CRLF) Else ConsoleWrite ("Standard Check: False" & @CRLF) EndIf ; Check for equality using the C Style (==) equality check If $array2 == $array1 Then ConsoleWrite ("C Style Check: True" & @CRLF) Else ConsoleWrite ("C Style Check: False" & @CRLF) EndIf ; Check for equality using for loops $result = True For $i = 0 To 1 For $j = 0 To 1 If $array1[$i][$j] <> $array2[$i][$j] Then $result = False EndIf Next Next ConsoleWrite ("For Loop Check: " & $result & @CRLF) EndFunc What this shows is that you can't check for equality between two arrays by saying either: If $array1 = $array2 -or- If $array1 == $array2 Please let me know if I'm doing anything wrong, or if there is already a method to check this. -D1Spartan Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 16, 2016 Moderators Share Posted May 16, 2016 D1Spartan, As you have discovered there is no short way to check array equality. Whenever I have to do this I start by using UBound to check for equal size and then either loop through the arrays checking each element or (if the array is not too large) use _ArrayToString and do a simple comparison. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
D1Spartan Posted May 16, 2016 Author Share Posted May 16, 2016 Melba, Thanks for the confirmation. The function I have created will take two arrays of any dimensional size (I have not checked where the limit of this is) and compare them for equality. I think this may be a nice addition to the Array UDF that exists already. I know you contributed to that UDF, so can you point me in the right direction to try to get it added? -D1Spartan Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 16, 2016 Moderators Share Posted May 16, 2016 D1Spartan, Quote I have not checked where the limit of this is From the Help file: VAR_SUBSCRIPT_ELEMENTS: 16,777,216 - Maximum number of elements for an array VAR_SUBSCRIPT_MAX: 64 - Maximum number of subscripts for an array Quote the right direction to try to get it added Post what you have and let us take a look. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
D1Spartan Posted May 16, 2016 Author Share Posted May 16, 2016 (edited) Melba, I understand max values (knew they were in the help file, but didn't look them up again) but what I was referring to is the fact that my function uses recursion and I don't know what the limit is that AutoIt imposes to prevent a stack overflow (number of times a function can call itself, probably in the help file as well but haven't looked). Also, are you suggesting just posting it here, on this post? I'm fine with that if that is what you meant. -D1Spartan Edited May 16, 2016 by D1Spartan Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 16, 2016 Moderators Share Posted May 16, 2016 D1Spartan, Quote are you suggesting just posting it here Yes. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
D1Spartan Posted May 16, 2016 Author Share Posted May 16, 2016 Proposed _ArrayCompare function: expandcollapse popupFunc _ArrayCompare (Const ByRef $array1, Const ByRef $array2) ; Check Subscripts $array1NumDimensions = UBound ($array1, 0) $array2NumDimensions = UBound ($array2, 0) ; Static Variables Static $arrayMatch Static $evaluationString = "" Static $dimension = 0 If $dimension = 0 Then If $array1NumDimensions <> $array2NumDimensions Then Return SetError (1, 0, False) EndIf If $array1NumDimensions = 0 Then Return SetError (2, 0, False) EndIf EndIf Switch $dimension Case 0 ; Start the iterations $arrayMatch = True $dimension = 1 _ArrayCompare ($array1, $array2) $dimension = 0 Case Else ; Save string to revert back $oldString = $evaluationString For $i = 0 To (UBound ($array1, $dimension) - 1) ; Add dimension to the string $evaluationString &= "[" & $i & "]" If $dimension = $array1NumDimensions Then ; Evaluate the string $arrayMatch = Execute ("$array1" & $evaluationString & " = $array2" & $evaluationString) ConsoleWrite ($evaluationString & " : " & $arrayMatch & @CRLF) Else ; Call the function for the next dimension $dimension += 1 _ArrayCompare ($array1, $array2) $dimension -= 1 EndIf ; Revert to old string $evaluationString = $oldString ; Dump out after the first mismatch If $arrayMatch = False Then ExitLoop EndIf Next EndSwitch Return $arrayMatch EndFunc Let me know what you think, or if you have questions. -D1Spartan Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 17, 2016 Moderators Share Posted May 17, 2016 D1Spartan, We are never too keen on recursive functions - too much room for error and confusion - plus we limit the built-in functions to a max of 2 dimensions (or else they get too unwieldy) which means we do not normally need it. I did some testing to see if your method was faster than those I suggested above - with the following results (times in secs): Method 100x100 1000x100 1000x1000 < array aize D1Spartan 0.39 2.87 28.5 recursive M23 Mode: 0 0.04 0.46 4.5 each element compare M23 Mode: 1 0.07 3.69 40.0 string row compare M23 Mode: 2 0.07 0.97 40.0 string column compare M23 Mode: 3 0.14 1.39 146.9 string whole array compare Here is the script I used if you want to try on your machine: expandcollapse popup#include <AutoItConstants.au3> #include <Array.au3> ConsoleWrite("Creating arrays" & @CRLF) Local $aArray_1[100][100] For $i = 0 To 99 For $j = 0 To 99 $aArray_1[$i][$j] = "Row " & $i & " - Col " & $j Next Next $aArray_2 = $aArray_1 ConsoleWrite("Comparing" & @CRLF) $nBegin = TimerInit() $iRet = _ArrayCompare_Spartan($aArray_1, $aArray_2) ConsoleWrite("Spartan: " & TimerDiff($nBegin) & @CRLF) If $iRet = 1 Then ConsoleWrite("Match" & @CRLF) EndIf $nBegin = TimerInit() $iRet = _ArrayCompare_M23($aArray_1, $aArray_2) ConsoleWrite("M23 0: " & TimerDiff($nBegin) & @CRLF) If $iRet = 1 Then ConsoleWrite("Match" & @CRLF) EndIf $nBegin = TimerInit() $iRet = _ArrayCompare_M23($aArray_1, $aArray_2, 1) ConsoleWrite("M23 1: " & TimerDiff($nBegin) & @CRLF) If $iRet = 1 Then ConsoleWrite("Match" & @CRLF) EndIf $nBegin = TimerInit() $iRet = _ArrayCompare_M23($aArray_1, $aArray_2, 2) ConsoleWrite("M23 2: " & TimerDiff($nBegin) & @CRLF) If $iRet = 1 Then ConsoleWrite("Match" & @CRLF) EndIf $nBegin = TimerInit() $iRet = _ArrayCompare_M23($aArray_1, $aArray_2, 3) ConsoleWrite("M23 3: " & TimerDiff($nBegin) & @CRLF) If $iRet = 1 Then ConsoleWrite("Match" & @CRLF) EndIf Func _ArrayCompare_Spartan (Const ByRef $array1, Const ByRef $array2) ; Check Subscripts $array1NumDimensions = UBound ($array1, 0) $array2NumDimensions = UBound ($array2, 0) ; Static Variables Static $arrayMatch Static $evaluationString = "" Static $dimension = 0 If $dimension = 0 Then If $array1NumDimensions <> $array2NumDimensions Then Return SetError (1, 0, False) EndIf If $array1NumDimensions = 0 Then Return SetError (2, 0, False) EndIf EndIf Switch $dimension Case 0 ; Start the iterations $arrayMatch = True $dimension = 1 _ArrayCompare_Spartan ($array1, $array2) $dimension = 0 Case Else ; Save string to revert back $oldString = $evaluationString For $i = 0 To (UBound ($array1, $dimension) - 1) ; Add dimension to the string $evaluationString &= "[" & $i & "]" If $dimension = $array1NumDimensions Then ; Evaluate the string $arrayMatch = Execute ("$array1" & $evaluationString & " = $array2" & $evaluationString) ;ConsoleWrite ($evaluationString & " : " & $arrayMatch & @CRLF) Else ; Call the function for the next dimension $dimension += 1 _ArrayCompare_Spartan ($array1, $array2) $dimension -= 1 EndIf ; Revert to old string $evaluationString = $oldString ; Dump out after the first mismatch If $arrayMatch = False Then ExitLoop EndIf Next EndSwitch Return $arrayMatch EndFunc Func _ArrayCompare_M23(Const ByRef $aArray1, Const ByRef $aArray2, $iMode = 0) ; Check if arrays If Not(IsArray($aArray1)) Or Not(IsArray($aArray2)) Then Return SetError(1, 0, 0) EndIf ; Check if same number of dimensions $iDims = UBound($aArray1, $UBOUND_DIMENSIONS) If $iDims <> UBound($aArray2, $UBOUND_DIMENSIONS) Then Return SetError(2, 0, 0) EndIf ; Check if same size $iRows = UBound($aArray1, $UBOUND_ROWS) $iCols = UBound($aArray1, $UBOUND_COLUMNS) If $iRows <> UBound($aArray2, $UBOUND_ROWS) Or $iCols <> UBound($aArray2, $UBOUND_COLUMNS) Then Return SetError(3, 0, 0) EndIf Local $sString_1, $sString_2 Switch $iMode Case 0 ; Compare each element For $i = 0 To $iRows - 1 For $j = 0 To $iCols - 1 If $aArray1[$i][$j] <> $aArray1[$i][$j] Then Return SetError(4, 0, 0) EndIf Next Next Case 1 ; Convert rows to strings For $i = 0 To $iRows - 1 For $j = 0 To $iCols - 1 $sString_1 &= $aArray1[$i][$j] $sString_2 &= $aArray2[$i][$j] Next If $sString_1 <> $sString_2 Then Return SetError(4, 0, 0) EndIf Next Case 2 ; Convert columnss to strings For $j = 0 To $iCols - 1 For $i = 0 To $iRows - 1 $sString_1 &= $aArray1[$i][$j] $sString_2 &= $aArray2[$i][$j] Next If $sString_1 <> $sString_2 Then Return SetError(4, 0, 0) EndIf Next Case 3 ; Convert whole array to string If _ArrayToString($aArray1) <> _ArrayToString($aArray2) Then Return SetError(4, 0, 0) EndIf EndSwitch ; Looks as if they match Return 1 EndFunc From those results, it looks as if the "each element compare" method is by far the fastest in all cases, but especially when the array is of any size, although the "full array string" method is not too bad when used on smaller arrays. So I do not think we will be adopting your suggested function into the standard library. However, please do not get discouraged by my response. We are always interested in seeing new ways of doing things - I have just been testing a proposal for a new way to sort 2D arrays which is very much faster than the current algorithm and which will be incorporated into the standard library very soon. So please do keep on with the good ideas. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
D1Spartan Posted May 17, 2016 Author Share Posted May 17, 2016 Melba, Thank you for the response. When I ran it on my work laptop (Dell, nothing special) the ratios were a bit different. Regardless, I can understand why (given the limitation of 2 dimensions) this method would not be incorporated into the standard library. I'm not discouraged by the way. My function fits my purposes, and I figured if it could help anyone else, great. Thanks again for looking at the code. -D1Spartan Link to comment Share on other sites More sharing options...
czardas Posted May 17, 2016 Share Posted May 17, 2016 A small tip for you D1Spartan. For a case sensitive <> comparison you can use this. #include <MsgBoxConstants.au3> Local $sStr1 = 'hello world' Local $sStr2 = 'HELLO WORLD' If $sStr1 <> $sStr2 Then ; case insensitive MsgBox($MB_OK, "case insensitive", 'strings are not equal') ElseIf Not ($sStr1 == $sStr2) Then ; case sensitive comparison MsgBox($MB_OK, "case sensitive", 'strings are not exactly equal') EndIf operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
jguinch Posted May 17, 2016 Share Posted May 17, 2016 You can also use _ArrayCompare from this UDF: ... but it uses _ArrayEnumValues rescursive function :-) Spoiler Network configuration UDF, _DirGetSizeByExtension, _UninstallList Firefox ConfigurationArray multi-dimensions, Printer Management UDF Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 17, 2016 Moderators Share Posted May 17, 2016 jguinch, I have nothing against recursion per se - but I do try and avoid it if possible as using it so often ends in tears unless you are very, very careful. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now