Gibbo Posted December 15, 2011 Posted December 15, 2011 (edited) 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 expandcollapse popup; #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 Edited December 15, 2011 by Gibbo
BrewManNH Posted December 15, 2011 Posted December 15, 2011 You're not checking for any array greater than a 2D array, if this is passed a 3D+ array it will crash. 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
Gibbo Posted December 15, 2011 Author Posted December 15, 2011 @BrewManNHDoes that mean the built in function doesnt check either? I have fixed this it now checks if the array is greater than two dimentions.Changed: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 NextTo: 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 IsDeclared($aArrayTmp[$iCC] & '$') Case False Assign($aArrayTmp[$iCC] & '$', 0, 1) $sHold &= $aArrayTmp[$iCC] & $vDelim EndSwitch NextNow it is insanely fast!"Uniqueify" An array of 500 random numbers (average of 5 results)4.97969129224458"Uniqueify" An array of 1000 random numbers (average of 5 results)10.0195612857199 expandcollapse popup; #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 ; 4 - Array has more than two dimensions ; 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 Not IsArray($aArray) Then Return SetError(1, 0, 0) ;Check to see if it is valid array If UBound($aArray, 0) > 2 Then Return SetError(4, 0, 0) ;Check to see if the array has more than two dimentions If $vDelim = "|" Then $vDelim = Chr(01) ; by SmOke_N, modified by litlmike ;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 IsDeclared($aArrayTmp[$iCC] & '$') Case False Assign($aArrayTmp[$iCC] & '$', 0, 1) $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
Gibbo Posted December 15, 2011 Author Posted December 15, 2011 (edited) Found another issue with error checking. Requests for a column greater than ubound($aArray,2) would cause a crash I rewrote all the error checking to make sure it caches everything. On a side note using the term "Dimentions" to describe different things is just plain confusing. Also "dimentions" should realy start at "0" for consistancy. (alltthough that would break existing scripts) EDIT: Script indenting failure EDIT2: needed "$iDimension-1" not "$iDimension" in one of the error checks (SEE Confusing!) expandcollapse popup; #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 ; 4 - Array has more than two dimensions ; 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 = "|") ;$aArray used to be ByRef, but litlmike altered it to allow for the choosing of 1 Array Dimension, without altering the original array If Not IsArray($aArray) Then Return SetError(1, 0, 0) ;Check to see if it is valid array If UBound($aArray, 0) > 2 Then Return SetError(4, 0, 0) ;Check to see if the array has more than two dimentions ;Check the given Dimension is Valid If $iDimension < 1 Then Return SetError(3, 0, 0) ;Check to see if dimension is greater than 0 If $iDimension - 1 > UBound($aArray, 2) Then Return SetError(3, 0, 0) ;Array dimension is invalid. ;Get the number of "Rows" Local $iUboundDim = UBound($aArray, 1) ;Get Number of "Rows" ;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 If $vDelim = "|" Then $vDelim = Chr(01) ; by SmOke_N, modified by litlmike 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 IsDeclared($aArrayTmp[$iCC] & '$') Case False Assign($aArrayTmp[$iCC] & '$', 0, 1) $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 Edited December 15, 2011 by Gibbo
wraithdu Posted December 15, 2011 Posted December 15, 2011 This wheel has been reinvented several times already. Here's a post I started with an idea I had. There's some good discussion in there and the solutions are much faster than even yours. My final version is in the first post.
Gibbo Posted December 15, 2011 Author Posted December 15, 2011 (edited) @wraithdu I had a look at your version before. It is fast but doesn't scale well for some reason. From your example: ($z = 500000, average of 5 runs each) Yours: 5.53712680343056 Mine: 2.93016771711739 Mine also doesnt rely on ObjCreate("Scripting.Dictionary"). EDIT: While trying some text (574896 items): $sFile= "C:\Windows\WindowsUpdate.log" $a=FileRead($sFile) $a=StringSplit($a,@TAB&@CRLF,2) _ArrayConcatenate($a,$a) _ArrayConcatenate($a,$a) _ArrayConcatenate($a,$a) ConsoleWrite(UBound($a)&@CRLF) I found that the version using ObjCreate("Scripting.Dictionary") drops entries: [117]|16:41:03:792 [118]|16:41:04:297 [119]|16:41:04:299 [120]|16:41:04:311 [121]|132c [122]|>>## RESUMED ## AU: Search for updates [CallId = {3EE45878-1C5F-45EC-9E1D-63F33F952797}] [123]|16:41:04:312 Should be: [117]|16:41:03:792 [118]|16:41:04:297 [119]|16:41:04:299 [120]|** END ** Agent: Finding updates [CallerId = AutomaticUpdates] [121]|16:41:04:311 [122]|132c [123]|>>## RESUMED ## AU: Search for updates [CallId = {3EE45878-1C5F-45EC-9E1D-63F33F952797}] [124]|16:41:04:312 Not sure if it is just the ones beginning with a * or not. Edited December 16, 2011 by Gibbo
Gibbo Posted December 16, 2011 Author Posted December 16, 2011 (edited) I used the method above to get the text from WindowsUpdate.log (574896 items) and used it to test an idea I had for matching with case sensitivity: Switch IsDeclared($aArrayTmp[$iCC] & '$') Case False Assign($aArrayTmp[$iCC] & '$', $aArrayTmp[$iCC], 1) ;Store the correct case item in the case insensitive variable named the same $sHold &= $aArrayTmp[$iCC] & $vDelim Case True And $iCase = 1 ;Only bother checking variable contents if case is important (otherwise its existance is enough) Switch StringInStr($vDelim & Eval($aArrayTmp[$iCC] & '$'), $vDelim & $aArrayTmp[$iCC] & $vDelim, 1) ;instead of checking a possibly massive $sHold just check the case insensitive variable of the same name Case 0 Assign($aArrayTmp[$iCC] & '$', Eval($aArrayTmp[$iCC] & '$') & $aArrayTmp[$iCC] & $vDelim, 1) $sHold &= $aArrayTmp[$iCC] & $vDelim EndSwitch EndSwitch Case insensitive: 1.82747950851224 Case sensitive: 4.11968048933211 three times slower but still quite fast for ~570000 items. expandcollapse popup; #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 ; 4 - Array has more than two dimensions ; 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 = "|") ;$aArray used to be ByRef, but litlmike altered it to allow for the choosing of 1 Array Dimension, without altering the original array If Not IsArray($aArray) Then Return SetError(1, 0, 0) ;Check to see if it is valid array If UBound($aArray, 0) > 2 Then Return SetError(4, 0, 0) ;Check to see if the array has more than two dimentions ;Check the given Dimension is Valid If $iDimension < 1 Then Return SetError(3, 0, 0) ;Check to see if dimension is greater than 0 If $iDimension - 1 > UBound($aArray, 2) Then Return SetError(3, 0, 0) ;Array dimension is invalid. ;Get the number of "Rows" Local $iUboundDim = UBound($aArray, 1) ;Get Number of "Rows" ;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 If $vDelim = "|" Then $vDelim = Chr(01) ; by SmOke_N, modified by litlmike 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 IsDeclared($aArrayTmp[$iCC] & '$') Case False Assign($aArrayTmp[$iCC] & '$', $aArrayTmp[$iCC] & $vDelim, 1) ;Store the correct case item (and delimiter) in the case insensitive variable named the same $sHold &= $aArrayTmp[$iCC] & $vDelim Case True And $iCase = 1 ;Only bother checking variable contents if case is important (otherwise its existance is enough) Switch StringInStr($vDelim & Eval($aArrayTmp[$iCC] & '$'), $vDelim & $aArrayTmp[$iCC] & $vDelim, 1) ;instead of checking a possibly massive $sHold just check the case insensitive variable of the same name Case 0 Assign($aArrayTmp[$iCC] & '$', Eval($aArrayTmp[$iCC] & '$') & $aArrayTmp[$iCC] & $vDelim, 1) $sHold &= $aArrayTmp[$iCC] & $vDelim EndSwitch 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 EDIT: Forgot to add the dilimeter when the variable is first stored Switch IsDeclared($aArrayTmp[$iCC] & '$') Case False Assign($aArrayTmp[$iCC] & '$', $aArrayTmp[$iCC], 1) ;Store the correct case item in the case insensitive variable named the same $sHold &= $aArrayTmp[$iCC] & $vDelim Should have been: Switch IsDeclared($aArrayTmp[$iCC] & '$') Case False Assign($aArrayTmp[$iCC] & '$', $aArrayTmp[$iCC] & $vDelim, 1) ;Store the correct case item (and delimiter) in the case insensitive variable named the same $sHold &= $aArrayTmp[$iCC] & $vDelim Edited December 16, 2011 by Gibbo
wraithdu Posted December 16, 2011 Posted December 16, 2011 The last I'll mention on the subject... I see you switched to the Assign() method. There's some discussion in the thread I linked why I don't like that method, even though it is the fastest. To each his own, as long as it suits your purpose.
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