Possible _ArrayUnique bug?
-
Recently Browsing 0 members
No registered users viewing this page.
-
Similar Content
-
By dejhost
Hello ,
Here are three stepts that I would like to speed up - if possible:
STEP 1: I am generating an array, containing binary numbers up to a certain amount of digits. My script adds leading zeros, so that each number has equal amount of digits.
Example: 14 digit Binary array:
I am using the code
For $i = 0 to 2^$bit-1 ; $bit amount of digits. for example: 14 $binary = ( Dec2Bin($i) ) ; Check length of binary string $adig = $bit - StringLen($binary) ; Determine how many leading 0 have to be added $zeros = "" For $j = 1 To $adig ; add leading "0"s $zeros = $zeros & "0" Next $BinArray[$i] = $zeros & $binary ;Write binary-number to file, leading "0" Next Func Dec2Bin($D) Return (BitShift($D, 1) ? Dec2Bin(BitShift($D, 1)) : "") & BitAnd($D, 1) EndFunc ;==> Dec2Bin() AutoIt v3.3.12.0 to generate the binary number.
STEP 2: I reduce the array to unique values. In my application, the binary-numbers do not have a start-bit or end-bit. This means, that
are actually the same numbers, and only one of them is to remain in the array. All alterations aren't unique and shall be removed. Here is my code:
For $i = 0 to Ubound($BinArray)-1 ; shift through all rows For $j = 1 to $bit ; shift through all the bits If $i = Ubound($BinArray) Then ; exit before exceeding the arrays boundries ExitLoop 2 EndIf $BinArray[$i] = StringRight ( $BinArray[$i], 1 ) & StringLeft ( $BinArray[$i], $bit-1 ) $BinArray = _ArrayUnique($BinArray, 0, 0, 0, 0, $ARRAYUNIQUE_AUTO) If @error <> 0 Then Msgbox(0, "Error in _ArrayUnique", "The Error Code is " & @error & " Abort.") Exit EndIf Next Next STEP 3: Finally, I write the remaining array into a text-file.
For $i = 0 to Ubound($BinArray)-1 FileWrite($hFileOpen, $i & @TAB & $BinArray[$i] & @CRLF) Next
So my question is: any idea how to speed up this procedure? There certainly is a way to do this smarter. Btw.: Step 2 is optional.
Thanks for helping,
dejhost
-
By Massi
Hi, I have update to the most recent Autoit version. I have a little problem with _ArrayUnique function.
If I have one array with two rows. _ArrayUnique crashes. I haven't any problem if there are more than two rows. I know that seems useless use this function with two rows, but these rows are the result of a search (generally I have more than two rows).
"C:\Program Files (x86)\AutoIt3\Include\Array.au3" (2290) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
Local $vFirstElem = ( ($iDims = 1) ? ($aArray[$iBase]) : ($aArray[$iColumn][$iBase]) )
Local $vFirstElem = ( ($iDims = 1) ? ($aArray[$iBase]) : (^ ERROR
#include <Array.au3> Dim $Test1[3][6]=[["11","12","13","14","15","16"],["21","22","23","24","25","26"],["21","22","23","24","25","26"]] Dim $Test[2][6]=[["11","12","13","14","15","16"],["21","22","23","24","25","26"]] Dim $result=0 _ArrayDisplay($Test1) _ArrayDisplay(_ArrayUnique($Test1, 2)) _ArrayDisplay($Test) _ArrayDisplay(_ArrayUnique($Test, 2)) I put a workaround that I don't use _ArrayUnique function if there are only two results
-
By czardas
This seems currently a hot topic. Anyway I have been thinking of trying out this idea for a while. This is in experimental stage and uses an old idea of declaring uniquely named variables followed by testing for their existence. I always thought it was an interesting approach. You can set the second parameter to case sensitive. R stands for Row. It returns either a one dimensional array or a two dimensional array of unique rows. Three datatypes are ignored: namely nested arrays, objects and DLLstructs. If someone knows a way to test these items quickly for uniqueness, or represent the data as binary then please enlighten me. Rows containing these items are simply just left in place. I'm not sure how efficient or what limitations this code has. Testing begins in the morning - oh, it already is morning. Meanwhile you might like to have a play with it.
; #FUNCTION# =================================================================================================================== ; Name...........: _ArrayUniqueR ; Description ...: Removes duplicate items (or rows) from a one (or two) dimensional array. ; Syntax.........: _ArrayUniqueR($aArray [, $bCaseSense = False]) ; Parameters.....; $aArray - The array containing duplicate data to be removed. ; Return values .: Success - Returns the unique array [ByRef]. ; $bCaseSense - [Optional] Set to true for case sensitive matches. Default value = False ; Failure sets @error as follows ; |@error = 1 1st parameter is not an array. ; |@error = 2 1st parameter has too many dimensions. ; Author ........: czardas ; Comments ......; Works with strings, numbers, binary, boolean values, pointers, functions and keywords (Null and Default). ; Integers of the same magnitude are treated as duplicates regardless of data type. ; All elements within a row must be duplicated (in the same positions) before removal takes place. ; This function does not remove rows containing objects, DLLStructs or other arrays. ; If you modify _ArrayUniqueR, avoid using variable names that could collide with internally generated names. ; ============================================================================================================================== Func _ArrayUniqueR(ByRef $aArray, $bCaseSense = Default) If Not IsArray($aArray) Then Return SetError(1) ; not an array Local $iDim = UBound($aArray, 0) If $iDim > 2 Then Return SetError(2) ; wrong number of dimensions Local $iRows = UBound($aArray) If $iRows < 2 Then Return ; array is already unique If $bCaseSense = Default Then $bCaseSense = False Local $iCols = ($iDim = 1) ? 1 : UBound($aArray, 2), _ $iItems = 0, $aFunction[1] = [0], $vElement, $iInt, $sName ; for each item, or row, generate unique names using word characters only For $i = 0 To $iRows -1 $sName = '' ; clear previous name For $j = 0 To $iCols -1 $vElement = ($iDim = 1) ? $aArray[$i] : $aArray[$i][$j] ; get the data contained in each element ; use non-hexadecimal characters (other than x) as datatype identifiers and convert the data to hexadecimal where necessary Switch VarGetType($vElement) Case 'String' If Not $bCaseSense Then $vElement = StringUpper($vElement) ; generates a case insensitive name segment $sName &= 's' & StringToBinary($vElement, 4) ; UTF8 [$SB_UTF8] Case 'Int32', 'Int64' ; use decimal without conversion ; the minus sign of a negative integer is replaced with 'g': to distinguish it from the positive value $sName &= ($vElement < 0) ? 'g' & StringTrimLeft($vElement, 1) : 'i' & $vElement Case 'Double' ; may be an integer $iInt = Int($vElement) $sName &= ($vElement = $iInt) ? (($iInt < 0) ? 'g' & StringTrimLeft($iInt, 1) : 'i' & $iInt) : 'h' & Hex($vElement) Case 'Bool' ; True or False $sName &= ($vElement = True) ? 't' : 'v' Case 'Binary' $sName &= 'y' & $vElement Case 'Ptr' $sName &= 'p' & $vElement Case 'Keyword' ; Default or Null (other variable declarations are illegal) $sName &= ($vElement = Default) ? 'w' : 'n' Case 'Function', 'UserFunction' ; string conversion will fail For $k = 1 To $aFunction[0] ; unique functions are stored in a separate array If $vElement = $aFunction[$k] Then ; this function has been encountered previously $sName &= 'u' & $k ContinueLoop 2 EndIf Next $aFunction[0] += 1 If $aFunction[0] > UBound($aFunction) -1 Then ReDim $aFunction[$aFunction[0] + 10] $aFunction[$aFunction[0]] = $vElement $sName &= 'u' & $aFunction[0] Case Else ; Array, Object or DLLStruct $sName = False ; set to ignore ExitLoop EndSwitch Next If $sName Then If IsDeclared($sName) = -1 Then ContinueLoop ; [$DECLARED_LOCAL] this row has been seen previously Assign($sName, "", 1) ; [else] declare each unique row as a new variable name EndIf ; overwrite the next row (assumes that the first duplicate will be found quite quickly) Switch $iDim Case 1 $aArray[$iItems] = $aArray[$i] Case 2 For $j = 0 To $iCols -1 $aArray[$iItems][$j] = $aArray[$i][$j] Next EndSwitch $iItems += 1 Next Switch $iDim Case 1 ReDim $aArray[$iItems] Case 2 ReDim $aArray[$iItems][$iCols] EndSwitch EndFunc ;==> _ArrayUniqueRExample:
#include <Array.au3> Local $aOddMix[14] = [Null, Null, True, True, False, False, Default, Default, Binary('0x0001'), Binary('0x0001'), Ptr(0x0001), Ptr(0x0001), MsgBox, MsgBox] _ArrayDisplay($aOddMix) $aUnique = _ArrayUniqueR($aOddMix) _ArrayDisplay($aOddMix)
-
By souldjer777
Good Morning AutoIT Geniuses
I have version 3.3.14.1.
I am experiencing an error with the default Array.au3 or _ArrayUnique
I believe it is with this single line in my au3 file...$aUniqueHostname = _ArrayUnique ($array01, 1)
SendAndLog("GEN_CSVMinRowLimit01 - Started", $tempzipdir & '\' & $LogFileName01, True) ; CSV Minimum Row Limit (FYI - default was originally set to 5000) $array01 = $twoDarray MsgBox (0, "", "You are here 1") $aUniqueHostname = _ArrayUnique ($array01, 1) ; FYI - The program never makes it to here: MsgBox (0, "", "You are here 2")"C:\Program Files (x86)\AutoIt3\Include\array.au3" (2297) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
If IsInt($aArray[$iBase]) Then
If IsInt(^ ERROR
; Title .........: Array
; AutoIt Version : 3.3.14.1
; Autocheck of first element
If $iIntType = $ARRAYUNIQUE_AUTO Then
If IsInt($aArray[$iBase]) Then
==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
Switch VarGetType($aArray[$iBase])
Case "Int32"
$iIntType = $ARRAYUNIQUE_FORCE32
Case "Int64"
$iIntType = $ARRAYUNIQUE_FORCE64
EndSwitch
Else
$iIntType = $ARRAYUNIQUE_FORCE32
EndIf
EndIf
I don't believe I've ever seen an error in the default au3 files. Is this something I am doing wrong?
I'm just trying to run my apps through the new version of AutoIT since the fix was put in for...
AutoIt3Help.exe reworked and digitally signed I have looked at bug trackers...
https://www.autoitscript.com/trac/autoit/ticket/3110
https://www.autoitscript.com/trac/autoit/ticket/3078
Is this related somehow - what version of AutoIT do you recommend I use?
Thanks!
-
By Gibbo
Recently I found myself needing to "Uniqueify" large arrays of data. Not happy with the speed I decided to check out how _ArrayUnique worked and if it could be improved.
Below is my overhauled version of _ArrayUnique.
"Uniqueify" An array of 500 random numbers (average of 5 results)
Old: 274.597787502462
New: 240.237994573652
"Uniqueify" An array of 1000 random numbers (average of 5 results)
Old: 1070.06629280595
New: 920.537746095923
Still not fast but faster
Changed ALL Dim's to Local's From the help file: "You should use Local or Global, instead of Dim, to explicitly state which scope is desired for a variable/constant/array." Changed: Dim $aArrayTmp[1] ;Declare blank array, which will hold the dimension declared by user For $i = 0 To $iUboundDim - 1 _ArrayAdd($aArrayTmp, <itemtoadd> ) ;$iDimension-1 to match Dimension Next _ArrayDelete($aArrayTmp, 0) ;Get rid of 1st-element which is blank To: Local $aArrayTmp[$iUboundDim] ;Declare array, which will hold the dimension declared by user For $i = 0 To $iUboundDim - 1 ;Loop through "Rows" $aArrayTmp[$i] = <itemtoadd> ;$iDimension-1 to match Dimension Next It is silly to declare a "blank" array (and delete the first "empty value")if you already know it's intended dimentions This also removed the need for _ArrayAdd (No more ReDim's YAY!) Changed If,Then, Else statements to Switch statements where appropriate for ease of reading (they are supposed to be faster too) Trimmed: If Not $iDimension > 0 Then Return SetError(3, 0, 0) ;Check to see if it is valid array dimension, Should be greater than 0 Else To: If $iDimension < 1 Then Return SetError(3, 0, 0) ;Check to see if it is valid array dimension, Should be greater than 0 Changed: $aArrayTmp = StringSplit(StringTrimRight($sHold, StringLen($vDelim)), $vDelim, 1) ;Split the string into an array Return $aArrayTmp ;SmOke_N's version used to Return SetError(0, 0, 0) To: $sHold = StringTrimRight($sHold, StringLen($vDelim)) $aArrayTmp = StringSplit($sHold, $vDelim, 1) ;Split the string into an array Return $aArrayTmp ;SmOke_N's version used to Return SetError(0, 0, 0) For clarity
; #FUNCTION# ==================================================================================================================== ; Name...........: _ArrayUnique ; Description ...: Returns the Unique Elements of a 1-dimensional array. ; Syntax.........: _ArrayUnique($aArray[, $iDimension = 1[, $iBase = 0[, $iCase = 0[, $vDelim = "|"]]]]) ; Parameters ....: $aArray - The Array to use ; $iDimension - [optional] The Dimension of the Array to use ; $iBase - [optional] Is the Array 0-base or 1-base index. 0-base by default ; $iCase - [optional] Flag to indicate if the operations should be case sensitive. ; 0 = not case sensitive, using the user's locale (default) ; 1 = case sensitive ; 2 = not case sensitive, using a basic/faster comparison ; $vDelim - [optional] One or more characters to use as delimiters. However, cannot forsee its usefullness ; Return values .: Success - Returns a 1-dimensional array containing only the unique elements of that Dimension ; Failure - Returns 0 and Sets @Error: ; 0 - No error. ; 1 - Returns 0 if parameter is not an array. ; 2 - _ArrayUnique failed for some other reason ; 3 - Array dimension is invalid, should be an integer greater than 0 ; Author ........: SmOke_N ; Modified.......: litlmike, Gibbo ; Remarks .......: Returns an array, the first element ($array[0]) contains the number of strings returned, the remaining elements ($array[1], $array[2], etc.) contain the unique strings. ; Related .......: _ArrayMax, _ArrayMin ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _ArrayUnique($aArray, $iDimension = 1, $iBase = 0, $iCase = 0, $vDelim = "|") Local $iUboundDim ;$aArray used to be ByRef, but litlmike altered it to allow for the choosing of 1 Array Dimension, without altering the original array If $vDelim = "|" Then $vDelim = Chr(01) ; by SmOke_N, modified by litlmike If Not IsArray($aArray) Then Return SetError(1, 0, 0) ;Check to see if it is valid array ;Checks that the given Dimension is Valid If $iDimension < 1 Then Return SetError(3, 0, 0) ;Check to see if it is valid array dimension, Should be greater than 0 ;If Dimension Exists, then get the number of "Rows" $iUboundDim = UBound($aArray, 1) ;Get Number of "Rows" If @error Then Return SetError(3, 0, 0) ;2 = Array dimension is invalid. ;If $iDimension Exists, And the number of "Rows" is Valid: Switch $iDimension = 1 Case False ;Makes sure the Array dimension desired is more than 1-dimensional Local $aArrayTmp[$iUboundDim] ;Declare array, which will hold the dimension declared by user For $i = 0 To $iUboundDim - 1 ;Loop through "Rows" $aArrayTmp[$i] = $aArray[$i][$iDimension - 1] ;$iDimension-1 to match Dimension Next Case Else ;Makes sure the Array dimension desired is 1-dimensional ;If Dimension Exists, And the number of "Rows" is Valid, and the Dimension desired is not > 1, then: ;For the Case that the array is 1-Dimensional Switch UBound($aArray, 0) Case 1 ;Makes sure the Array is only 1-Dimensional Local $aArrayTmp[$iUboundDim] ;Declare array, which will hold the dimension declared by user For $i = 0 To $iUboundDim - 1 $aArrayTmp[$i] = $aArray[$i] Next Case Else ;For the Case that the array is 2-Dimensional Local $aArrayTmp[$iUboundDim] ;Declare array, which will hold the dimension declared by user For $i = 0 To $iUboundDim - 1 $aArrayTmp[$i] = $aArray[$i][$iDimension - 1] ;$iDimension-1 to match Dimension Next EndSwitch EndSwitch Local $sHold ;String that holds the Unique array info For $iCC = $iBase To $iUboundDim - 1 ;Loop Through array ;If Not the case that the element is already in $sHold, then add it Switch StringInStr($vDelim & $sHold, $vDelim & $aArrayTmp[$iCC] & $vDelim, $iCase) Case False $sHold &= $aArrayTmp[$iCC] & $vDelim EndSwitch Next If $sHold Then $sHold = StringTrimRight($sHold, StringLen($vDelim)) $aArrayTmp = StringSplit($sHold, $vDelim, 1) ;Split the string into an array Return $aArrayTmp ;SmOke_N's version used to Return SetError(0, 0, 0) EndIf Return SetError(2, 0, 0) ;If the script gets this far, it has failed EndFunc ;==>_ArrayUnique
-
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