colombeen Posted October 2, 2014 Share Posted October 2, 2014 (edited) Hi has anyone created a script to compare 2 arrays like this : compare the 2 arrays - the items that are only in array 1 go into a new array - the items that are only in array 2 go into another new array - the items that are in both arrays go into another new array like this : Global $Compare1[10] = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12] Global $Compare2[10] = [1, 2, 3, 4, 5, 6, 8, 10, 12, 13] $whatsLeftOfCompare1 = [7, 9, 11] $whatsLeftOfCompare2 = [2, 4, 13] $whatsInBoth = [1, 3, 5, 6, 8, 10, 12] I want to use this to compare 2 arrays with Active Directory rights and check which rights users have in comon and which rights they have separatly. if any anyone has created this before and would like to share it, I would appreciate it very much! I was searching on the forum but I didn't find anything that looks like this and I'm not really sure how I could achieve this without using like 4 or 5 loops Edited October 2, 2014 by colombeen Link to comment Share on other sites More sharing options...
Solution iamtheky Posted October 2, 2014 Solution Share Posted October 2, 2014 #include <Array.au3> Global $aCompare1[10] = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12] Global $aCompare2[10] = [1, 2, 3, 4, 5, 6, 8, 10, 12, 13] Global $aBoth[0] For $i = ubound($aCompare1) - 1 to 0 step -1 $iMatch = _ArraySearch($aCompare2 , $aCompare1[$i]) If $iMatch <> -1 then _ArrayAdd($aBoth , $aCompare1[$i]) _ArrayDelete($aCompare1 , $i) _ArrayDelete($aCompare2, $iMatch) EndIf Next For $i = ubound($aCompare2) - 1 to 0 step -1 $iMatch = _ArraySearch($aCompare1 , $aCompare2[$i]) If $iMatch <> -1 then _ArrayAdd($aBoth , $aCompare2[$i]) _ArrayDelete($aCompare2 , $i) _ArrayDelete($aCompare1 , $iMatch) EndIf Next _ArrayDisplay ($aBoth, "In Both") _ArrayDisplay ($aCompare1, "Only in Compare 1") _ArrayDisplay ($aCompare2, "Only in Compare 2") MikahS, robertocm and SkysLastChance 3 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
colombeen Posted October 2, 2014 Author Share Posted October 2, 2014 THAT IS AWESOME! thx boththose Link to comment Share on other sites More sharing options...
kylomas Posted October 2, 2014 Share Posted October 2, 2014 Another way (boththose beat me to it!)... #include <array.au3> local $Compare1 = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12] local $Compare2 = [1, 2, 3, 4, 5, 6, 8, 10, 12, 13, 19, '', 'whatever'] local $Common[1] for $1 = ubound($Compare1) - 1 to 0 step -1 for $2 = ubound($Compare2) - 1 to 0 step -1 if $Compare1[$1] = $Compare2[$2] then redim $Common[ubound($Common)+1] $Common[ubound($Common)-1] = $Compare2[$2] _arraydelete($Compare1,$1) _arraydelete($Compare2,$2) ExitLoop EndIf Next next _arraydisplay($Compare1,'Compare1') _arraydisplay($Compare2,'Compare2') _arraydisplay($Common,'Common') Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill Link to comment Share on other sites More sharing options...
mikell Posted October 2, 2014 Share Posted October 2, 2014 If the array is big the repetitive use of Redim (also included in _ArrayAdd and _ArrayDelete) will cause the script to be terribly slow rootx 1 Link to comment Share on other sites More sharing options...
iamtheky Posted October 2, 2014 Share Posted October 2, 2014 (edited) So this is without redim, but when you are reading them out to whatever you are doing with the data preface it with: If $array[$i] <> "" then .... #include <Array.au3> Global $aCompare1[10] = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12] Global $aCompare2[10] = [1, 2, 3, 4, 5, 6, 8, 10, 12, 13] Global $aBoth[ubound($aCompare1) * 2] Global $x = 0 For $i = ubound($aCompare1) - 1 to 0 step -1 $iMatch = _ArraySearch($aCompare2 , $aCompare1[$i]) If $iMatch <> -1 then $aBoth[$x] = $aCompare1[$i] $aCompare1[$i] = "" $aCompare2[$iMatch] = "" $x += 1 EndIf Next For $i = ubound($aCompare2) - 1 to 0 step -1 $iMatch = _ArraySearch($aCompare1 , $aCompare2[$i]) If $iMatch <> -1 then $aBoth[$x] = $aCompare2[$i] $aCompare2[$i] = "" $aCompare1[$iMatch] = "" $x += 1 EndIf Next _ArrayDisplay ($aCompare1, "Only in Compare 1") _ArrayDisplay ($aCompare2, "Only in Compare 2") _ArrayDisplay ($aBoth, "In Both") Or someone smrt will come clean up the blanks all fancy like. Edited October 2, 2014 by boththose ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
Gianni Posted October 2, 2014 Share Posted October 2, 2014 do not know if is to be considered a bug or what, but bothdhose way fails if duplicate values are present in an array (because it says only in array1 while it's in both. for example double the number 10 in first array) Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
BrewManNH Posted October 2, 2014 Share Posted October 2, 2014 Here's one way I'd do it. I'm sure the comparisons could be done better, and getting rid of _ArraySearch would probably help too. I used _ArrayShuffle so that I could make sure it would find the proper duplicates/unique items no matter what order they were in the arrays. expandcollapse popup#include <Array.au3> Global $Compare1[10] = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12] _ArrayShuffle($Compare1) Global $Compare2[10] = [1, 2, 3, 4, 5, 6, 8, 10, 12, 13] _ArrayShuffle($Compare2) Global $whatsLeftOfCompare1[UBound($Compare1)] Global $whatsLeftOfCompare2[UBound($Compare2)] Global $whatsInBoth[100] Global $K = 0, $L = 0 For $I = 0 To UBound($Compare1) - 1 _ArraySearch($Compare2, $Compare1[$I]) If Not @error Then $whatsInBoth[$K] = $Compare1[$I] $K += 1 Else $whatsLeftOfCompare1[$L] = $Compare1[$I] $whatsLeftOfCompare2[$L] = $Compare2[$I] $L += 1 EndIf Next $L = 0 For $I = 0 To UBound($Compare2) - 1 _ArraySearch($Compare1, $Compare2[$I]) If @error Then $whatsLeftOfCompare2[$L] = $Compare2[$I] $L += 1 EndIf Next ReDim $whatsInBoth[$K] ReDim $whatsLeftOfCompare1[$L] ReDim $whatsLeftOfCompare2[$L] _ArrayDisplay($whatsInBoth, "$whatsInBoth") _ArrayDisplay($whatsLeftOfCompare1, "$whatsLeftOfCompare1") _ArrayDisplay($whatsLeftOfCompare2, "$whatsLeftOfCompare2") 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 GudeHow 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 Link to comment Share on other sites More sharing options...
iamtheky Posted October 2, 2014 Share Posted October 2, 2014 (edited) nah no bug, there are many cases where that will have to be modified it was just a crude example, a couple i have found are: 1) if there is dupes in the same array, or the potential, you get Chimps result, I would run arrayunique on them first if feasible. 2) if there are a different number of items in the arrays then one of the loops will blow up, as i am using the ubound of the target 2a) If there are dupes in the same array, and you perform the delete right after you find them (in the same fashion as the other arraysearch-->arraydelete, rather than using arrayunique), thus redimming and creating arrays of two different sizes, same explosion. Edited October 2, 2014 by boththose ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
mikell Posted October 2, 2014 Share Posted October 2, 2014 It seems that there are no issues using Scripting.Dictionary #include <Array.au3> Local $a[11] = [1, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12] Local $b[12] = [1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 13, 14] Local $sda = ObjCreate("Scripting.Dictionary") Local $sdb = ObjCreate("Scripting.Dictionary") Local $sdc = ObjCreate("Scripting.Dictionary") For $i In $a $sda.Item($i) Next For $i In $b $sdb.Item($i) Next For $i In $a If $sdb.Exists($i) Then $sdc.Item($i) Next $asd3 = $sdc.Keys() For $i In $asd3 If $sda.Exists($i) Then $sda.Remove($i) If $sdb.Exists($i) Then $sdb.Remove($i) Next $asd1 = $sda.Keys() $asd2 = $sdb.Keys() _ArrayDisplay($asd1, "$asd1") _ArrayDisplay($asd2, "$asd2") _ArrayDisplay($asd3, "$asd3") iamtheky, Norm73, pixelsearch and 1 other 4 Link to comment Share on other sites More sharing options...
iamtheky Posted October 2, 2014 Share Posted October 2, 2014 That is beautiful, "advantages of scripting.dictionary over array functions" totally needs its own thread. ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
kylomas Posted October 2, 2014 Share Posted October 2, 2014 (edited) It seems that there are no issues using Scripting.Dictionary In this case it works out as the scripting dictionary overwrites the duplicate key... expandcollapse popup#include <Array.au3> Local $a[11] = [1, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12] Local $b[12] = [1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 13, 14] Local $sda = ObjCreate("Scripting.Dictionary") Local $sdb = ObjCreate("Scripting.Dictionary") Local $sdc = ObjCreate("Scripting.Dictionary") For $i In $a $sda.Item($i) Next For $i In $b $sdb.Item($i) Next ; -------------------------------------- $aKeys = $sdb.Keys() For $i = 0 To ubound($aKeys) -1 ConsoleWrite($aKeys[$i] & @CRLF) Next ;--------------------------------------- For $i In $a If $sdb.Exists($i) Then $sdc.Item($i) Next $asd3 = $sdc.Keys() For $i In $asd3 If $sda.Exists($i) Then $sda.Remove($i) If $sdb.Exists($i) Then $sdb.Remove($i) Next $asd1 = $sda.Keys() $asd2 = $sdb.Keys() _ArrayDisplay($asd1, "$asd1") _ArrayDisplay($asd2, "$asd2") _ArrayDisplay($asd3, "$asd3") @boththose - I agree, for me personally anyway, when I stopped using VBS I also stopped using the scripting dictionary. As mikell demonstated it may be time to start looking at it as another alternative. kylomas Edited October 2, 2014 by kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill Link to comment Share on other sites More sharing options...
Gianni Posted October 2, 2014 Share Posted October 2, 2014 (edited) no claim of improvement, just another one this returns results in a 2D array col1 contains values contained only in first array, col2 those contained only in the second one, and col3 in both #include <Array.au3> Local $a[11] = [1, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12] Local $b[12] = [1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 13, 14] _ArrayDisplay(_Separate($a, $b)) Func _Separate(ByRef $in0, ByRef $in1) $in0 = _ArrayUnique($in0, 0, Default, Default, 0) $in1 = _ArrayUnique($in1, 0, Default, Default, 0) Local $z[2] = [UBound($in0), UBound($in1)], $low = 1 * ($z[0] > $z[1]), $aTemp[$z[Not $low]][3], $aOut = $aTemp, $aNdx[3] For $i = 0 To $z[Not $low] - 1 If $i < $z[0] Then $aTemp[$i][0] = $in0[$i] If $i < $z[1] Then $aTemp[$i][1] = $in1[$i] Next For $i = 0 To $z[$low] - 1 $x = _ArrayFindAll($aTemp, $aTemp[$i][$low], 0, 0, 1, 0, Not $low) If Not @error Then ; both For $j = 0 To UBound($x) - 1 $aTemp[$x[$j]][2] = 1 Next $aOut[$aNdx[2]][2] = $aTemp[$i][$low] $aNdx[2] += 1 Else ; only in $low $aOut[$aNdx[$low]][$low] = $aTemp[$i][$low] $aNdx[$low] += 1 EndIf Next For $i = 0 To $z[Not $low] - 1 If $aTemp[$i][2] <> 1 Then $aOut[$aNdx[Not $low]][Not $low] = $aTemp[$i][Not $low] $aNdx[Not $low] += 1 EndIf Next ReDim $aOut[_ArrayMax($aNdx)][3] Return $aOut EndFunc ;==>_Separate Edited October 2, 2014 by Chimp robertocm 1 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
iamtheky Posted July 13, 2018 Share Posted July 13, 2018 (edited) * Edited July 13, 2018 by iamtheky ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
Norm73 Posted June 12 Share Posted June 12 (edited) I needed such a function, but it was necessary to compare the values in stilts in certain rows. I decided to make a universal function that compares both 1D and 2D values by columns or rows By default, all values are compared as strings and optionally as numbers. expandcollapse popup#include <Array.au3> Local $Array1[2][12] = [[0,0,0,0,0,0,0,0,0,0,0,0],["TA",1,3,5,17,6,7,8,9,10,11,"MG"]] Local $Array2[10][2] = [[1,0], [2,0], [2,0], [3,0], [4,0], [5,0], [6,0], [8,0], [10,0], ["MG",0]] Local $aExRet = _ArrayCompare($Array1, $Array2, 0, 1, 2, 0, 0, 1, 0, 1) _ArrayDisplay($aExRet) Dim $Array1[14] = [1,"ZU",3,5,17,6,7,8,"GH",10,11,12] Dim $Array2[12][2] = [[0,1], [0,1], [0,3], [0,5], [0,17], [0,6], [0,7], [0,"GH"], [0,9], [0,10], [0,11], [0,12]] Local $aExRet = _ArrayCompare($Array1, $Array2, 0, 0, 1, 0, 1, 1, 0, 1) _ArrayDisplay($aExRet) Func _ArrayCompare($Array1, _ ; Array1 zum Abgleich Const ByRef $Array2, _ ; Array2 zum Abgleich $iStr1 = 0, _ ; Startindex für Array1 $i1rc = 0, _ ; Param. für Array1; Spalte von 1 oder 2D Array1 // Zeile von 2D wenn $iRg1 = 2 $iRg1 = 1, _ ; Param. für Array1; nur 1 oder 2; Bei 1 wird in allen Zeilen gesucht, bei 2 in allen Spalten $iStr2 = 0, _ ; Startindex für Array2 $i2rc = 0, _ ; Param. für Array2; Spalte von 1 oder 2D Array2 // Zeile von 2D wenn $iRg1 = 2 $iRg2 = 1, _ ; Param. für Array2; nur 1 oder 2; Bei 1 wird in allen Zeilen gesucht, bei 2 in allen Spalten $iDig = 0, _ ; 0 => alle Werte werden als String vergliechen; wenn 1 als Zahlen $iRtS = 1) ; 1 => ein 2D-Array mit dem Ergebnis für [x][0]-$Array1, [x][1]-$Array1 und [x][2]-Spalte mit allen vorhandenen in beiden Arrays ; ^^^^^ wenn 0 => ohne Spalte [x][2]-Spalte mit allen vorhandenen in beiden Arrays If Not IsArray($Array1) Or Not IsArray($Array2) Then Return SetError(-1) If ($iRg1 > 2) Or ($iRg1 < 1) Then Return SetError(-3) If ($iRg2 > 2) Or ($iRg2 < 1) Then Return SetError(-4) Local $iDmsA = UBound($Array1, 0) Local $iDmsB = UBound($Array2, 0) If ($iRg1 = 2 And $iDmsA = 1) Or ($iRg2 = 2 And $iDmsB = 1) Then Return SetError(-5) Local $nUb1 = UBound($Array1, $iRg1) Local $nUb2 = UBound($Array2, $iRg2) Local $oDic1 = ObjCreate("Scripting.Dictionary") Local $oDic2 = ObjCreate("Scripting.Dictionary") Local $oDic3 = ObjCreate("Scripting.Dictionary") For $iN = $iStr1 To $nUb1 -1 If $iDmsA = 1 Then $Array1[$iN] = ($iDig ? (Number($Array1[$iN])) : (String($Array1[$iN]))) $oDic1.Item($Array1[$iN]) Else If $iRg1 = 1 Then $Array1[$iN][$i1rc] = ($iDig ? (Number($Array1[$iN][$i1rc])) : (String($Array1[$iN][$i1rc]))) $oDic1.Item($Array1[$iN][$i1rc]) Else $Array1[$i1rc][$iN] = ($iDig ? (Number($Array1[$i1rc][$iN])) : (String($Array1[$i1rc][$iN]))) $oDic1.Item($Array1[$i1rc][$iN]) EndIf EndIf Next For $iN = $iStr2 To $nUb2 -1 If $iDmsB = 1 Then $oDic2.Item($iDig ? (Number($Array2[$iN])) : (String($Array2[$iN]))) Else If $iRg2 = 1 Then $oDic2.Item($iDig ? (Number($Array2[$iN][$i2rc])) : (String($Array2[$iN][$i2rc]))) Else $oDic2.Item($iDig ? (Number($Array2[$i2rc][$iN])) : (String($Array2[$i2rc][$iN]))) EndIf EndIf Next For $iN = $iStr1 To $nUb1 -1 If $iDmsA = 1 Then If $oDic2.Exists($Array1[$iN]) Then $oDic3.Item($Array1[$iN]) EndIf Else If $iRg1 = 1 Then If $oDic2.Exists($Array1[$iN][$i1rc]) Then $oDic3.Item($Array1[$iN][$i1rc]) EndIf Else If $oDic2.Exists($Array1[$i1rc][$iN]) Then $oDic3.Item($Array1[$i1rc][$iN]) EndIf EndIf EndIf Next Local $aRet3 = $oDic3.Keys() Local $nUb3 = UBound($aRet3)-1 For $iN = 0 To $nUb3 If $oDic1.Exists($aRet3[$iN]) Then $oDic1.Remove($aRet3[$iN]) EndIf If $oDic2.Exists($aRet3[$iN]) Then $oDic2.Remove($aRet3[$iN]) EndIf Next $oDic3.RemoveAll() Local $aRet1 = $oDic1.Keys() $nUb1 = UBound($aRet1)-1 $oDic1.RemoveAll() Local $aRet2 = $oDic2.Keys() $nUb2 = UBound($aRet2)-1 $oDic2.RemoveAll() If Not $iRtS Then $nUb3 = -1 EndIf Local $nExUB = (($nUb1 > $nUb2) ? (($nUb1 > $nUb3) ? $nUb1 : $nUb3) : (($nUb2 > $nUb3) ? $nUb2 : $nUb3)) Local $aExRet[$nExUB+1][($iRtS ? 3 : 2)] For $iN = 0 To $nExUB If $iN <= $nUb1 Then $aExRet[$iN][0] = $aRet1[$iN] EndIf If $iN <= $nUb2 Then $aExRet[$iN][1] = $aRet2[$iN] EndIf If $iN <= $nUb3 Then $aExRet[$iN][2] = $aRet3[$iN] EndIf Next Return $aExRet EndFunc Edited June 12 by Norm73 Link to comment Share on other sites More sharing options...
pixelsearch Posted June 13 Share Posted June 13 Norm73, glad you found a solution for your need I never saw this old thread before today, so I studied just now mikell's good solution (based on Scripting Dictionary) It seems to me that mikell's script can be improved, by the use of 3 loops instead of 4, with the same result, like this : #include <Array.au3> Local $a[11] = [1, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12] ; some duplicate values (1 found twice) Local $b[12] = [1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 13, 14] ; some duplicate values (2 found twice) Local $sda = ObjCreate("Scripting.Dictionary") Local $sdb = ObjCreate("Scripting.Dictionary") Local $sdc = ObjCreate("Scripting.Dictionary") For $i In $a $sda.Item($i) ; unique keys Next For $i In $b $sdb.Item($i) ; unique keys Next For $i In $sda If $sdb.Exists($i) Then $sdc.Item($i) $sda.Remove($i) $sdb.Remove($i) EndIf Next $asd1 = $sda.Keys() $asd2 = $sdb.Keys() $asd3 = $sdc.Keys() _ArrayDisplay($asd1, "$asd1") ; 7, 9, 11 _ArrayDisplay($asd2, "$asd2") ; 2, 4, 13, 14 _ArrayDisplay($asd3, "$asd3") ; 1, 3, 5, 6, 8, 10, 12 Another thing we could think about is : should the 3rd loop be... For $i In $sda ; or For $i In $sdb ...I think it depends on the number of elements in each dictionary. In our case they're nearly the same so it doesn't matter which one you'll choose, but imagine one dictionary got only 3 elements and the second dictionary got 10000 elements, then it seems quicker to execute the For...In loop 3 times (by using the shorter dictionary), instead of looping 10000 times by choosing the longer dictionary. Anyway, results will be same, no matter the dictionary you choose in the 3rd For...In loop If you guys think something is wrong in this reworked script, please be kind to indicate it, thanks. ioa747 1 Link to comment Share on other sites More sharing options...
ioa747 Posted June 14 Share Posted June 14 (edited) pixelsearch following and exploring your latest posts prompts me to share the results expandcollapse popup; https://www.autoitscript.com/forum/topic/164728-compare-2-arrays-with-3-arrays-as-a-result/?do=findComment&comment=1534659 #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <Array.au3> ; I do 3 laps to compare For $i = 1 To 3 ConsoleWrite("- Round " & $i & " -----------------" & @CRLF) FuncSpeedTest('_Dictionary()') FuncSpeedTest('_Map()') Next ;-------------------------------------------------------------------------------------------------------------------------------- Func _Map() Local $a[11] = [1, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12] ; some duplicate values (1 found twice) Local $b[12] = [1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 13, 14] ; some duplicate values (2 found twice) Local $mda[] Local $mdb[] Local $mdc[] For $i In $a $mda[$i] = $i ; unique keys Next For $i In $b $mdb[$i] = $i ; unique keys Next Local $ada = MapKeys($mda) For $vKey In $ada If MapExists($mdb, $vKey) Then $mdc[$vKey] = $vKey MapRemove($mda, $vKey) MapRemove($mdb, $vKey) EndIf Next Local $asd1 = MapKeys($mda) Local $asd2 = MapKeys($mdb) Local $asd3 = MapKeys($mdc) _Print($asd1, "$asd1") _Print($asd2, "$asd2") _Print($asd3, "$asd3") EndFunc ;==>_Map ;-------------------------------------------------------------------------------------------------------------------------------- Func _Dictionary() Local $a[11] = [1, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12] ; some duplicate values (1 found twice) Local $b[12] = [1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 13, 14] ; some duplicate values (2 found twice) Local $sda = ObjCreate("Scripting.Dictionary") Local $sdb = ObjCreate("Scripting.Dictionary") Local $sdc = ObjCreate("Scripting.Dictionary") For $i In $a $sda.Item($i) ; unique keys Next For $i In $b $sdb.Item($i) ; unique keys Next For $i In $sda If $sdb.Exists($i) Then $sdc.Item($i) $sda.Remove($i) $sdb.Remove($i) EndIf Next Local $asd1 = $sda.Keys() Local $asd2 = $sdb.Keys() Local $asd3 = $sdc.Keys() _Print($asd1, "$asd1") _Print($asd2, "$asd2") _Print($asd3, "$asd3") EndFunc ;==>_Dictionary ;-------------------------------------------------------------------------------------------------------------------------------- Func _Print(ByRef $aArray, $sTitle) Local $sTxt = "" For $i = 0 To UBound($aArray) - 1 $sTxt &= $aArray[$i] & ", " Next $sTxt = StringTrimRight($sTxt, 2) ConsoleWrite($sTitle & ": " & $sTxt & @CRLF) EndFunc ;==>_Print ;-------------------------------------------------------------------------------------------------------------------------------- Func FuncSpeedTest($sExecute) Local $hTimer = TimerInit() Execute($sExecute) ConsoleWrite($sExecute & " processed in: " & TimerDiff($hTimer) & " ms " & @LF & @LF) EndFunc ;==>FuncSpeedTest ;-------------------------------------------------------------------------------------------------------------------------------- if I did it right and I'm not missing anything, the difference was quite significant (considering that the sample is quite small) Edited June 14 by ioa747 pixelsearch 1 I know that I know nothing Link to comment Share on other sites More sharing options...
pixelsearch Posted June 14 Share Posted June 14 @ioa747 thanks for the speed test between Map and Scripting.Dictionary 3 hours ago, ioa747 said: if I did it right and I'm not missing anything, the difference was quite significant (considering that the sample is quite small) What about we try the tests on larger arrays ? Below is your reworked speed test. Now we can define the number of rows in each array with this line : Local $iRows = 50 ; after this 1st test, try other values for $iRow, like 5000, then 10000, 20000... The 2 arrays generated for each test will be exactly the same (because of the SRandom instruction, for example 4 for the 1st array, 5 for the 2nd array) Could you please run this reworked script, first with the indicated value (50, it will ConsoleWrite the results, just for checking) . Then re-run it with $iRows = 5000, 10000... (no more ConsoleWrite of values in these cases, just the timer difference) Does the Map part is still quicker than the Scripting.Dictionary part, when the arrays grow bigger ? Thanks expandcollapse popup; AutoIt 3.3.16.1 (Map) ; Comparing speed between Map and Scripting.Dictionary #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <Array.au3> Local $iRows = 50 ; after this 1st test, try other values for $iRow, like 5000, then 10000, 20000... ConsoleWrite("$iRows = " & $iRows & @crlf & @crlf) ; I do 3 laps to compare For $i = 1 To 3 ConsoleWrite("- Round " & $i & " -----------------" & @CRLF) FuncSpeedTest('_Dictionary($iRows)') FuncSpeedTest('_Map($iRows)') Next ;-------------------------------------------------------------------------------------------------------------------------------- Func _Map($iRows) Local $a[$iRows], $b[$iRows] GenerateArrayInt($a, $iRows, 4) ; seed value for random number generation (to generate exactly the same array for each test) GenerateArrayInt($b, $iRows, 5) ; ditto Local $mda[] Local $mdb[] Local $mdc[] For $i In $a $mda[$i] = $i ; unique keys ; $mda[$i] = Null ; no need to associate a value to each unique key (to match the script dictionary test) Next ; _ArrayDisplay(_Map2D($mda), "$mda : Map Keys & Values") ; comment out this line during tests ! For $i In $b $mdb[$i] = $i ; unique keys Next Local $ada = MapKeys($mda) For $vKey In $ada If MapExists($mdb, $vKey) Then $mdc[$vKey] = $vKey MapRemove($mda, $vKey) MapRemove($mdb, $vKey) EndIf Next Local $asd1 = MapKeys($mda) Local $asd2 = MapKeys($mdb) Local $asd3 = MapKeys($mdc) If $iRows <= 50 Then _Print($asd1, "$asd1") If $iRows <= 50 Then _Print($asd2, "$asd2") If $iRows <= 50 Then _Print($asd3, "$asd3") EndFunc ;==>_Map ;-------------------------------------------------------------------------------------------------------------------------------- Func _Dictionary($iRows) Local $a[$iRows], $b[$iRows] GenerateArrayInt($a, $iRows, 4) ; seed value for random number generation (to generate exactly the same array for each test) GenerateArrayInt($b, $iRows, 5) ; ditto Local $sda = ObjCreate("Scripting.Dictionary") Local $sdb = ObjCreate("Scripting.Dictionary") Local $sdc = ObjCreate("Scripting.Dictionary") For $i In $a $sda.Item($i) ; unique keys Next For $i In $b $sdb.Item($i) ; unique keys Next For $i In $sda If $sdb.Exists($i) Then $sdc.Item($i) $sda.Remove($i) $sdb.Remove($i) EndIf Next Local $asd1 = $sda.Keys() Local $asd2 = $sdb.Keys() Local $asd3 = $sdc.Keys() If $iRows <= 50 Then _Print($asd1, "$asd1") If $iRows <= 50 Then _Print($asd2, "$asd2") If $iRows <= 50 Then _Print($asd3, "$asd3") EndFunc ;==>_Dictionary ;-------------------------------------------------------------------------------------------------------------------------------- Func _Print(ByRef $aArray, $sTitle) Local $sTxt = "" For $i = 0 To UBound($aArray) - 1 $sTxt &= $aArray[$i] & ", " Next $sTxt = StringTrimRight($sTxt, 2) ConsoleWrite($sTitle & ": " & $sTxt & @CRLF) EndFunc ;==>_Print ;-------------------------------------------------------------------------------------------------------------------------------- Func FuncSpeedTest($sExecute) Local $hTimer = TimerInit() Execute($sExecute) ConsoleWrite($sExecute & " processed in: " & TimerDiff($hTimer) & " ms " & @LF & @LF) EndFunc ;==>FuncSpeedTest ;-------------------------------------------------------------------------------------------------------------------------------- Func GenerateArrayInt(ByRef $aArray, $iRows, $iSeed) SRandom($iSeed) For $i = 0 To $iRows - 1 $aArray[$i] = Random(0, $iRows, 1) ; 1 to return integer values Next EndFunc ;==>GenerateArrayInt ;-------------------------------------------------------------------------------------------------------------------------------- Func _Map2D(Const ByRef $mMap) Local $aMapKeys = MapKeys($mMap) Local $aMap2D[Ubound($aMapKeys)][2] Local $iRow = - 1 For $vKey In $aMapKeys $iRow += 1 ; 0+ $aMap2D[$iRow][0] = $vKey $aMap2D[$iRow][1] = $mMap[$vKey] Next Return $aMap2D EndFunc ;==>_Map2D ;-------------------------------------------------------------------------------------------------------------------------------- ioa747 1 Link to comment Share on other sites More sharing options...
pixelsearch Posted June 16 Share Posted June 16 @ioa747 hello You were right about the comparative speed between scripting dictionary and map I'm just testing the precedent script on a win 11 laptop with 16Go ram (AMD Ryzen 7 5800H with Radeon Graphics, 3.20 GHz) With 30000 elements, scripting dictionary takes 1s when map takes 0.5s (approx) Then with 50000 or 100000 elements, it's the same kind of results : map always takes half the time than scripting dictionary On a much slower PC with much less ram, it seems to be the opposite (scripting dictionary takes less time than map when the number of elements icrease) As most people got today a quick laptop, then let's stick with your conclusion (unless somebody got a different opinion), so let's use Map instead of Scripting dictionary on recent computers. argumentum and ioa747 1 1 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