Jump to content

Recommended Posts

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

; #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
Posted

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

Posted

@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
Posted (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!)

; #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
Posted

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.

Posted (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 by Gibbo
Posted (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.

; #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
Posted

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.

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
×
×
  • Create New...