Jump to content

_ArrayUnique Overhaul


Gibbo
 Share

Recommended Posts

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
Edited by Gibbo
Link to comment
Share on other sites

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 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

Link to comment
Share on other sites

@BrewManNH

Does 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
    Next

To: :D

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

Now 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

:)

; #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
Link to comment
Share on other sites

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!)

; #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 by Gibbo
Link to comment
Share on other sites

@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 by Gibbo
Link to comment
Share on other sites

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.

; #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 by Gibbo
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...