#include-once
#include <Array.au3>
; #FUNCTION# ============================================================================
; Name.............: 	ArrayUnique
; Description ...: 	Returns the Unique Elements of a 1-dimensional or 2-dimensional array.
; Syntax...........: 	_ArrayUnique($aArray[, $iBase = 0, oBase = 0])
; Parameters ...: 	$aArray - The Array to use
;                  			$iBase  - [optional] Is the input Array 0-base or 1-base index.  0-base by default
;                  			$oBase  - [optional] Is the output Array 0-base or 1-base index.  0-base by default
; Return values:	Success - Returns a 1-dimensional or 2-dimensional array containing only the unique elements
;                  			Failure - Returns 0 and Sets @Error:
;                  			0 - No error.
;                  			1 - Returns 0 if parameter is not an array.
;                  			2 - Array has more than 2 dimensions
;                  			3 - Array is already unique
;                  			4 - when source array is selected as one base but UBound(array) - 1 <> array[0] / array[0][0]
;                  			5 - Scripting.Dictionary cannot be created for 1D array unique code
; Author .........: 	UEZ 2010 for 2D-array, Yashied for 1D-array (modified by UEZ)
; Version ........: 	0.96 Build 2010-11-20 Beta
; Remark ........:	check is always case sensitive
; =======================================================================================
Func ArrayUnique($aArray, $iBase = 0, $oBase = 0)
	If Not IsArray($aArray) Then Return SetError(1, 0, 0) ;not an array
	If UBound($aArray, 0) > 2 Then Return SetError(2, 0, 0) ;array is greater than a 2D array
	If UBound($aArray) = $iBase + 1 Then Return SetError(3, 0, $aArray) ;array is already unique because of only 1 element
	Local $dim = UBound($aArray, 2), $i
	If $dim Then ;2D array
		If $iBase And UBound($aArray) - 1 <> $aArray[0][0] Then Return SetError(4, 0, 0)
		Local $oD = ObjCreate('Scripting.Dictionary')
		If @error Then Return SetError(5, 0, 0)
		Local $i, $j, $k = $oBase, $l, $s, $aTmp, $flag, $sSep = Chr(01)
		Local $aUnique[UBound($aArray)][$dim]
		If Not $oBase Then $flag = 2
        For $i =  $iBase To UBound($aArray) - 1
			For $j = 0 To $dim - 1
				$s &= $aArray[$i][$j] & $sSep
			Next
			If Not $oD.Exists($s) And StringLen($s) > 3 Then
				$oD.Add($s, $i)
				$aTmp = StringSplit(StringTrimRight($s, 1), $sSep, 2)
				For $l = 0 To $dim - 1
					$aUnique[$k][$l] = $aTmp[$l]
				Next
				$k += 1
			EndIf
			$s = ""
		Next
        $oD.RemoveAll
		$oD = ""
		If $k > 0 Then
			If $oBase Then $aUnique[0][0] = $k - 1
			ReDim $aUnique[$k][$dim]
		Else
			ReDim $aUnique[1][$dim]
		EndIf
	Else ;1D array
		If $iBase And UBound($aArray) - 1 <> $aArray[0] Then Return SetError(4, 0, 0)
		Local $sData = '', $sSep = ChrW(160), $flag
		For $i = $iBase To UBound($aArray) - 1
			If Not IsDeclared($aArray[$i] & '$') Then
				Assign($aArray[$i] & '$', 0, 1)
				$sData &= $aArray[$i] & $sSep
			EndIf
		Next
		If Not $oBase Then $flag = 2
		Local $aUnique = StringSplit(StringTrimRight($sData, 1), $sSep, $flag)
	EndIf
	Return SetError(0, 0, $aUnique)
EndFunc   ;==>ArrayUnique