1D-2DArray Doppelte Elemente finden und Entfernen

  • Hi Leute!

    Habe mir gedacht das diese Beiden Funktionen vielleicht nützlich für den einen o. anderen diese Func sucht in ein 1D-Array noch Doppelt vorkommende Einträge
    man kann sie wenn man möchte löschen lassen und das angepasste Array ausgeben lassen.

    FindDuplicateDeleteArray:
    Ist entstanden aus der Idee und Umsetzung von AspirinJunkie entstanden wo ich schon mal so eine Funktion geschrieben habe.

    Spoiler anzeigen
    [autoit]


    ; #FUNCTION# ;=============================================================================================
    ;
    ; Name...........: FindDuplicate_DeleteArray
    ; Description ...: Findet Elemente deren Name mehrmals vorkommt
    ; Syntax.........: FindDuplicate_DeleteArray($avArray [, $Rein = 0])
    ; Parameters ....: $avArray - Array1D [ $Rein - Array Doppelte einträge entfernen 0-nein / 1-Ja]
    ; Return values .: Erfolg - 1D-Array mit den Doppelten Elemente o. 1D-Array ohne den Doppelten Elemente
    ; Fehler - Gibt -1 zurück und setzt @error:
    ; |1 - Fehler beim erstellen der Collections
    ; |2 - Kein 1DArray
    ; Author ........: Idee von AspirinJunkie / [ created by Kleiner27 http://www.AutoIT.de ]
    ; Modified.......:
    ; Remarks .......: Benötigt .Net für Collections
    ; Related .......:
    ; Link ..........;
    ; Example .......; No
    ; [ created by Kleiner27 http://www.AutoIT.de ] 01.05.2010
    ; ;=========================================================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func FindDuplicate_DeleteArray(ByRef $avArray, $Rein = 0)
    Local $iEle = ObjCreate('System.Collections.Queue')
    If @error Then Return SetError(1, 1, -1)
    Local $iDub = ObjCreate('Scripting.Dictionary')
    If @error Then Return SetError(1, 2, -1)
    Local $iRad = ObjCreate('Scripting.Dictionary')
    If @error Then Return SetError(1, 3, -1)
    If (UBound($avArray, 0) <> 1) Then Return SetError(2, 0, '')
    Local $iDir, $iTmp, $iCount = 0
    For $i = 0 To UBound($avArray) - 1
    $iEle.Enqueue($avArray[$i])
    $iDir = $iEle.Dequeue
    If $iDub.Exists($iDir) Then
    If $iRad.Exists($iDir) Then
    $iTmp = $iRad($iDir)
    $iRad.Remove($iDir)
    $iRad.Add($iDir, $iTmp & '[' & $i)
    Else
    $iRad.Add($iDir, '[' & $iDub($iDir) & '[' & $i)
    EndIf
    Else
    $iDub.Add($iDir, $i)
    EndIf
    Next
    Local $R_Array[$iRad.Count], $Tmp_Array
    If ($Rein) Then
    For $i In $iRad.Keys
    $Tmp_Array = StringSplit(StringTrimLeft($iRad($i), 1), '[')
    If IsArray($Tmp_Array) Then
    For $i = 1 To UBound($Tmp_Array) - 2
    $avArray[$Tmp_Array[$i]] = ''
    Next
    EndIf
    Next
    $Tmp_Array = ''
    If IsString($Tmp_Array) Then
    For $_i_ In $avArray
    If ($_i_ > '') Then $Tmp_Array &= '|' & $_i_
    Next
    EndIf
    $Tmp_Array = StringSplit(StringTrimLeft($Tmp_Array, 1), '|')
    If IsArray($Tmp_Array) Then
    For $i = 0 To UBound($Tmp_Array) - 2
    $Tmp_Array[$i] = $Tmp_Array[$i + 1]
    Next
    ReDim $Tmp_Array[UBound($Tmp_Array) - 1]
    Return $Tmp_Array
    EndIf
    EndIf
    For $i In $iRad.Keys
    $R_Array[$iCount] = $i & ' ' & $iRad($i)
    $iCount += 1
    Next
    Return $R_Array
    EndFunc ;==>FindDuplicate_DeleteArray

    [/autoit]

    ArraySortingFindDuplicateDelete:
    Diese Funktion hat mehrere Optionen unter einem Dach
    [Sortieren, Doppelte Einträge finden, gegeben falls Array anpassen (Löschen ) , Start u. Ende Bestimmen]

    Spoiler anzeigen
    [autoit]


    ; #FUNCTION# ;=============================================================================================
    ;
    ; Name...........: ArraySorting_FindDuplicate_Delete
    ; Description ...: Findet Elemente deren Name mehrmals vorkommt
    ; Syntax.........: ArraySorting_FindDuplicate_Delete($avArray[, $Abst [, $Start [, $End [, $Rein [, $Sort ]]]]])
    ;
    ; Parameters ....: $avArray - Array1D
    ; $Abst - Wenn auf 1 gesetzt, sortieren absteigend
    ; $Start - Index des Array beim Start
    ; $End - Index der Array beim Ende
    ; $Rein - Wenn auf 1 gesetzt, Bei der ausgabe alle Doppelte Eldemente Entfernen
    ; $Sort - Wenn auf 1 gesetzt, Nur Sortiert ausgeben in Kombination mit $Abst ist möglich
    ;
    ; Return values .: Erfolg - 1D-Array mit den Doppelten Elemente o. 1D-Array ohne den Doppelten Elemente o.
    ; 1D-Array nur Sortiert wenn 1=aubsteigend
    ;
    ; Fehler - Gibt -1 zurück und setzt @error:
    ; |1 - Wenn keine Array
    ; |2 - Wenn Start größer als Ende
    ; |3 - Wnn kein 1D-Array
    ;
    ; Author ........: Kleiner27
    ; Modified.......:
    ; Remarks .......:
    ; Related .......: _Sort()
    ; Link ..........;
    ; Example .......;
    ;
    ; Integriert u. Modified; _ArrayReverse() u. _ArraySort()-1D
    ;
    ;
    ; [ created by Kleiner27 http://www.AutoIT.de ] 01.05.2010
    ; ;=========================================================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func ArraySorting_FindDuplicate_Delete(ByRef $avArray, $Abst = 0, $Start = 0, $End = 0, $Rein = 0, $Sort = 0)
    If Not IsArray($avArray) Then Return SetError(1, 0, -1)
    If ($Start > $End) Then Return SetError(1, 2, -1)
    If (UBound($avArray, 0) <> 1) Then Return SetError(1, 3, -1)
    Local $Start_2 = $Start
    Local $Tmp, $Tmp_Array, $iSTelle
    Local $iUB = UBound($avArray) - 1
    Local $iDelim = '|', $Delim = '[', $Leer = ''
    If ($End < 1 Or $End > $iUB) Then $End = $iUB
    _Sort($avArray, $Start, $End)
    If ($Abst) Then
    For $i = $Start_2 To Int(($Start_2 + $iUB - 1) / 2)
    $Tmp = $avArray[$i]
    $avArray[$i] = $avArray[$iUB]
    $avArray[$iUB] = $Tmp
    $iUB -= 1
    Next
    EndIf
    If ($Sort) Then Return $avArray
    For $i = $Start To $End
    $iSTelle = $Leer
    For $e = $i To $End
    If ($avArray[$e] <> $avArray[$i]) Then ExitLoop
    $iSTelle &= $Delim & $e
    Next
    If ($e - $i < 2) Then ContinueLoop
    $Tmp_Array &= $iDelim & $avArray[$i] & ' ' & $iSTelle
    $i += ($e - $i - 1)
    Next
    If ($Rein) Then
    If ($Tmp_Array = $Leer) Then Return $avArray
    $Tmp_Array = StringSplit(StringTrimLeft($Tmp_Array, 1), $Delim)
    If IsArray($Tmp_Array) Then
    For $i = 1 To UBound($Tmp_Array) - 1
    If (StringIsDigit($Tmp_Array[$i]) = 1) Then $avArray[$Tmp_Array[$i]] = $Leer
    Next
    EndIf
    $Tmp_Array = $Leer
    If IsString($Tmp_Array) Then
    For $_i_ In $avArray
    If ($_i_ > $Leer) Then $Tmp_Array &= $iDelim & $_i_
    Next
    EndIf
    EndIf
    If ($Tmp_Array = $Leer) Then Return $avArray
    $Tmp_Array = StringSplit(StringTrimLeft($Tmp_Array, 1), $iDelim)
    If IsArray($Tmp_Array) Then
    For $i = 0 To UBound($Tmp_Array) - 2
    $Tmp_Array[$i] = $Tmp_Array[$i + 1]
    Next
    ReDim $Tmp_Array[UBound($Tmp_Array) - 1]
    Return $Tmp_Array
    EndIf
    EndFunc ;==>ArraySorting_FindDuplicate_Delete

    [/autoit] [autoit][/autoit] [autoit]

    Func _Sort(ByRef $avArray, ByRef $iStart, ByRef $iEnd)
    Local $Tmp, $K = $iEnd, $G = $iStart
    Local $oPru = $avArray[Int(($iStart + $iEnd) / 2)]
    If (($iEnd - $iStart) < 15) Then
    For $i = $iStart + 1 To $iEnd
    $Tmp = $avArray[$i]
    For $e = $i - 1 To $iStart Step -1
    If ($Tmp >= $avArray[$e]) Then ExitLoop
    $avArray[$e + 1] = $avArray[$e]
    Next
    $avArray[$e + 1] = $Tmp
    Next
    Return (0)
    EndIf
    Do
    While ($avArray[$G] < $oPru)
    $G += 1
    WEnd
    While ($avArray[$K] > $oPru)
    $K -= 1
    WEnd
    If ($G <= $K) Then
    $Tmp = $avArray[$G]
    $avArray[$G] = $avArray[$K]
    $avArray[$K] = $Tmp
    $G += 1
    $K -= 1
    EndIf
    Until $G > $K
    _Sort($avArray, $iStart, $K)
    _Sort($avArray, $G, $iEnd)
    EndFunc ;==>_Sort

    [/autoit]

    Diese Funktion ist erst mal auf 1D-Array aufgebaut möchte auf Feedback warten vielleicht hat jemand noch Ideen
    Verbesserungsvorschläge und dann werde ich die Func auf 2d-Array erweitern.

    _ObjektAr2DDubDel:

    Ubdate : Bug Behoben und Doppelt so schnell wie vorher im 2DArray Vergleich.

    Spoiler anzeigen
    [autoit]


    ; #FUNCTION# ;=============================================================================================
    ;
    ; Name...........: _ObjektAr2DDubDel
    ; Description ...: Findet Elemente deren Name mehrmals vorkommt und Löst dies aus ein 1D o. 2D Array
    ; Syntax.........: _ObjektAr2DDubDel($avArray)
    ; Parameters ....: $avArray - Array1D o. Array2D
    ; Return values .: Erfolg - 1D-Array o. Array2D mit den Doppelten Elemente
    ;
    ; Fehler - Gibt -1 zurück und setzt @error:
    ; |1 - Fehler beim erstellen der Collections
    ;
    ; Author ........: Kleiner27 http://www.AutoIT.de
    ; Modified.......:
    ; Remarks .......:
    ; Related .......:
    ; Link ..........;
    ; Example .......; No
    ; [ created by Kleiner27 http://www.AutoIT.de ] 06.05.2010
    ; ;=========================================================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _ObjektAr2DDubDel(ByRef $avArray)
    Local $ScripDict = ObjCreate('Scripting.Dictionary')
    If @error Then Return SetError(1, 1, -1)
    Local $iTmp
    Local $TmpArray
    Local $iTmp_Save
    Local $TmpArrayReturn[1][2]
    Local $iEnd = UBound($avArray)
    Local $1D2D = UBound($avArray, 2)
    If @error = 2 Then
    $ScripDict.RemoveAll
    For $For In $avArray
    If Not $ScripDict.Exists($For) Then $ScripDict.Add($For, 0)
    Next
    Return $ScripDict.Keys()
    Else
    For $1D = 0 To $iEnd - 1
    $TmpArray &= '|'
    For $2D = 0 To $1D2D - 1
    $TmpArray &= $avArray[$1D][$2D]
    Next
    Next
    $TmpArray = StringSplit(StringTrimLeft($TmpArray, 1), '|')
    For $i = 1 To UBound($TmpArray) - 1
    $iTmp = $TmpArray[$i]
    If Not $ScripDict.Exists($iTmp) Then
    $ScripDict.Add($iTmp, 0)
    $iTmp_Save &= '|' & $i - 1 & $iTmp
    EndIf
    Next
    $1D = 0
    ReDim $TmpArrayReturn[$iEnd][$1D2D]
    $TmpArray = StringSplit(StringTrimLeft($iTmp_Save, 1), '|')
    For $i = 1 To UBound($TmpArray) - 1
    For $2D = 0 To $1D2D - 1
    $TmpArrayReturn[$1D][$2D] = $avArray[Number($TmpArray[$i])][$2D]
    Next
    $1D += 1
    Next
    ReDim $TmpArrayReturn[$1D][$1D2D]
    Return $TmpArrayReturn
    EndIf
    EndFunc ;==>_ObjektAr2DDubDel

    [/autoit]

    Test Code für _ObjektAr2DDubDel

    Spoiler anzeigen
    [autoit]

    #include 'Array.au3'
    #include '_ObjektAr2DDubDel.au3'

    [/autoit] [autoit][/autoit] [autoit]

    ;$max = 99
    ;$max = 999
    ;$max = 9999
    $max = 99999
    ;$max = 999999
    ;Dim $Zu_Sa[$max]
    Dim $Zu_Sa[$max][15]
    For $i = 0 To $max - 1
    ;$Zu_Sa[$i] = Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1)) & '.' & Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1))
    $Zu_Sa[$i][0] = Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1)) & '.' & Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1)) & Chr(Random(65, 67, 1))
    $Zu_Sa[$i][1] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][2] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][3] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][4] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][5] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][6] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][7] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][8] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][9] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][10] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][11] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][12] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][13] = $Zu_Sa[$i][0]
    $Zu_Sa[$i][14] = $Zu_Sa[$i][0]
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    sleep(2000)
    ConsoleWrite('start' & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Local $iTimer = TimerInit()
    Dim $A = _ObjektAr2DDubDel($Zu_Sa)
    ;_ArraySort($A)
    _ArrayDisplay($A , ' Nach u. Time : _ObjektAr2DDubDel' & Round(TimerDiff($iTimer)))

    [/autoit]

    Viel Spass.


    LG Kleiner

  • Falls es nur um 1D-Arrays geht und auch kein Index benötigt wird (also $aArray[0]=Anzahl der Einträge)
    dann ist folgendes am schnellsten:

    [autoit]

    Func _ArrayUnique_($aA)
    Local $aR, $oD = ObjCreate('Scripting.Dictionary')
    For $i = 0 To UBound($aA) - 1
    If Not $oD.Exists($aA[$i]) Then $oD.Add($aA[$i], 0)
    Next
    $aR = $oD.Keys()
    Return $aR
    EndFunc

    [/autoit]
  • Hi Leute!

    Erstmal Danke schön für euer Interesse und Ideen!

    BugFix
    An deiner reinen Array such kann man ja nicht mehr viel ändern supper durchdacht nur ist diese Funktion ein wenig zu Langsam!
    Habe aber deine Idee der 2D prüfung übernommen für die _ObjektAr2DDubDel :D

    eukalyptus
    Wow verdamt schnell habe die Funktion _ArrayUnique_ eingebunden für die Func _ObjektAr2DDubDel :D

    Update Post#1 = _ObjektAr2DDubDel
    Verarbeitet 1D u. D2 Array und das sehr schnell.

    LG Kleiner

  • Kleiner
    Du suchst doch immer nach auch den letzten Verbesserungen.
    So sollte die sowieso schon schnelle Funktion von Eukalyptus noch nen Tick fixer arbeiten:

    Spoiler anzeigen
    [autoit]

    Func _ArrayUnique_(ByRef $aA)
    Local Static $oD = ObjCreate('Scripting.Dictionary')
    For $i In $aA
    If Not $oD.Exists($i) Then $oD.Add($i, 0)
    Next
    Local $aR = $oD.Keys()
    $oD.RemoveAll
    Return $aR
    EndFunc

    [/autoit]

    Einmal editiert, zuletzt von AspirinJunkie (7. Mai 2010 um 00:05)

  • Hi!

    AspirinJunkie
    Tatsächlich auf großen Array holt deine Version noch ein wenig raus Klasse :thumbup:

    Habe ein Bug in der Version von gestern gefunden: Behoben u. Doppelt so schnell im 2DArray Vergleich

    Update: Post#1


    LG Kleiner