Array logisch sortieren BugFix hier was für dich ;)

  • Nach 3 Stunden Google
    Bin ich echt am verzweifeln..

    Array Logisch Sortieren

    In php gibt es so eine schöne Funktion, womit man Array´s Logisch Sortieren kann

    Code
    beispiel 1
    beispiel 2
    beispiel 11
    beispiel 4
    beispiel 3
    beispiel 10

    Was kommt raus bei einem normalen arrysort

    Code
    beispiel 1
    beispiel 10
    beispiel 11
    beispiel 2
    beispiel 3
    beispiel 4

    Ich hätte es aber gerne so

    Code
    beispiel 1
    beispiel 2
    beispiel 3
    beispiel 4
    beispiel 10
    beispiel 11

    Logische Sortierung

    Habe leider nichts gefunden

    Und da BugFix hier der ArrayGuru ist ;)
    Daher das auffällige Topic ;)

    2 Mal editiert, zuletzt von Gummibaer (30. Juli 2009 um 22:45)

    • Offizieller Beitrag

    _ArraySort sortiert schon "richtig", denn es handelt sich bei Deinem Array ja um Strings und nicht um Zahlen.
    Willst Du eine andere Sortierung musst Du Deine eigene Sortierroutine schreiben. Dabei kommt es dann darauf an, was sich in dem Array für Daten befinden. Für Dein Beispiel funktioniert diese Routine:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    Global $array[20]
    For $i = 0 To 19
    $array[$i] = 'Beispiel ' & $i
    Next
    _ArraySort($array)
    _ArrayDisplay($array, 'Array mit _ArraySort')
    _NumArraySort($array)
    _ArrayDisplay($array, 'Array mit _NumArraySort')

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

    Func _NumArraySort(ByRef $array)
    Local $tmp
    For $i = 0 To UBound($array) - 2
    For $j = $i + 1 To UBound($array) - 1
    If Number(StringRegExpReplace($array[$j], '\D*(\d*)\D*', '$1')) < Number(StringRegExpReplace($array[$i], '\D*(\d*)\D*', '$1')) Then
    $tmp = $array[$i]
    $array[$i] = $array[$j]
    $array[$j] = $tmp
    EndIf
    Next
    Next
    EndFunc

    [/autoit]


    Das ist jetzt nur ein SimpleSort-Verfahren, eignet sich also nicht so sehr für große Arrays (langsam).

  • Danke dir das array ist nicht größ wenn es hochkommt 40 einträge ;) wird einmalig sortiert

    Ich sagte nicht das es Falsch macht ich suchte eine möglichkeit das Array Logisch zu sortieren ;)

    Ich danke dir ;)

    Werde es sofort testen wenn ich fertig bin mit schnabulierwanzen töten

    • Offizieller Beitrag

    Manchmal ist die Logik halt auch relativ. ;)
    Sagen wir mal: Du möchtest das Array numerisch (statt alphanumerisch) sortieren.
    Mit nur 40 Einträgen ist das SimpleSort-Verfahren kein Problem. Ich hab's jetzt nicht ausgiebig getestet, aber ich würde sagen, so bis ca. 1000 Array-Elemente sollte das noch ganz akzeptabel laufen.
    Darüber sollte man lieber ein QuickSort benutzen.

    Ein Problem könnte mit meiner Funktion auftreten, wenn die Array-Elemente mehrere Zahlen enthalten (z.B. "Beispiel 12 blabla 45").
    Falls das bei Dir der Fall ist, melde Dich nochmal, dann kann man das RegExp-Pattern vielleicht noch verfeinern.

  • Ähm also ich erkläre dir mal den sinn und zweck warumm ich das brauche
    Um meien DVD Sammlung zu sichern konvertiere ich die mir ins Xvid format .. da ich kein Anständiges Progi gefunden haben was das selber gut erkenn und eine Batch liste verfügt dachte ich mir ich mach das halt selber
    DVDFab kann gut mit commandline und bringt saubere ergebnisse
    Ich habe mir daher ein Gui erstellt was nach einem Ordner als suche fragt wo es die suche nach DVD Verzeichnissen aufnimmt
    Die treffer zeigt er mir in einer Listbox an
    Da der dateipfad lang sein kann habe ich mich entschlossen nur den letzten ordner anzeigen zu lassen
    aba nicht den VideoTS ordner sondern eine ebene höher immer
    Dadurch hab ich auf gut deutsch nichts als ordner namen da in der Listbox
    Wenn diese nun Doof sortiert ist schaut das einfach nicht aus..
    Als Perfektionist bei solch sachen sollte das natürlich passen

    Ich erhalte eigentlich immer den vollpfad
    zur VIDEO_TS.IFO in einem string mit | getrennt ( Super für listbox )
    wenn ich das so lasse einfach das in ein zweites array in der selben reihenfolge die vollen pfade und in dem anderen nur den DVD Namen setze passt das das ja auch
    Nur leider unschön sortiert.
    eigentlich müsste ich zwei arrays sortieren wobei in den einem eben die namens liste ist und in den anderen vollerpfad.

    Zurück zu sache..
    Also sind die Dateinamen willkührlich
    Können alles enthalten .. und mit einem logischen sortieren wie es PHP machen kann wäre mir am besten beholfen

    EDIT:

    2 arrays sortieren muss nicht mehr sein ich speicher einfach in einer hashtable die pfade zu den einträgen
    Funktioniert auch soweit super ...

    nur ist durch den _NumArraySort
    die Alphabetische reinfolge zerstört *kopfKratz*

    2 Mal editiert, zuletzt von Gummibaer (30. Juli 2009 um 15:29)

    • Offizieller Beitrag

    Noch eine Variante von mir:

    Spoiler anzeigen
    [autoit]

    #include <array.au3>
    Global $aTest[10][2] = [ _
    ['Beispiel5',''], _
    ['Beispiel7',''], _
    ['Beispiel1',''], _
    ['Beispiel6',''], _
    ['Beispiel4',''], _
    ['Beispiel9',''], _
    ['Beispiel8',''], _
    ['Beispiel3',''], _
    ['Beispiel10',''], _
    ['Beispiel2','']]

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

    Local $pos
    For $i = 0 To UBound($aTest) -1
    $pos = _LastNumPosInStr($aTest[$i][0], -1)
    $aTest[$i][1] = Number(StringMid($aTest[$i][0], $pos, StringLen($aTest[$i][1])-($pos-1)))
    Next
    _ArraySort($aTest,0,0,0,1)
    _ArrayDisplay($aTest)

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

    Func _LastNumPosInStr($sString, $occurrence=1)
    Local $start = 1, $ende = StringLen($sString), $step = 1
    If $occurrence = -1 Then
    $start = $ende
    $ende = 1
    $step = -1
    EndIf
    For $i = $start To $ende Step $step
    If StringRegExp((StringMid($sString, $i, 1)), '\D', 0) Then ExitLoop
    Next
    If $occurrence = 1 Then
    Return $i-1
    Else
    Return $i+1
    EndIf
    EndFunc

    [/autoit]
  • Danke BugFix

    Leider aber auch das Problem das es sich nur an den Zahlen Orientitiert

  • Logische Sortierung

    sagte ich extra ;)
    In PHP heist dies natsort

    Datei Name logisch Sortieren eben ;)
    Sorry wenn Ihr das falsch aufgenommen habt
    ZB
    Vorher:
    acd1
    abc1
    hallo ich bin doof
    abc12
    fsdfd fdsf
    abc 3
    abc4
    acf2

    Natürliche sortierung wäre dann
    Nacher:
    abc1
    abc3
    abc4
    abc12
    acd1
    acf2
    fsdfd fdsf
    hallo ich bin doof

    ;) hab da was nach langen weiterem googeln gefunden

    natsort
    Leider blick ich durch den code nicht ganz durch
    wie ich das für meine Zwecke nutzen könnte.

    • Offizieller Beitrag

    Eine kleine Änderung der Funktion:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    Global $array[8] = ['acd1','abc1','hallo ich bin doof','abc12','fsdfd fdsf','abc3','abc4','acf2']
    _ArraySort($array)
    _ArrayDisplay($array, 'Array mit _ArraySort')
    _NumArraySort($array)
    _ArrayDisplay($array, 'Array mit _NumArraySort')

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

    Func _NumArraySort(ByRef $array)
    _ArraySort($array)
    Local $tmp
    For $i = 0 To UBound($array) - 2
    For $j = $i + 1 To UBound($array) - 1
    If StringRegExpReplace($array[$j], '(\D*)\d*\D*', '$1') = StringRegExpReplace($array[$i], '(\D*)\d*\D*', '$1') Then
    If Number(StringRegExpReplace($array[$j], '\D*(\d*)\D*', '$1')) < Number(StringRegExpReplace($array[$i], '\D*(\d*)\D*', '$1')) Then
    $tmp = $array[$i]
    $array[$i] = $array[$j]
    $array[$j] = $tmp
    EndIf
    EndIf
    Next
    Next
    EndFunc

    [/autoit]
  • So, da der Code für diese Funktion fast völlig korrupt ist, hab ich sie nochmal neu in _ArraySort eingebaut:

    Spoiler anzeigen
    [autoit]

    ; #FUNCTION# ;===============================================================================
    ;
    ; Name...........: _NaturalCompare
    ; Description ...: Compare two strings using Natural (Alphabetical) sorting.
    ; Syntax.........: _NaturalCompare($s1, $s2, $iCase = 0)
    ; Parameters ....: $s1, $s2 - Strings to compare
    ; $iCase - Case sensitive or insensitive comparison
    ; |0 - Case insensitive (default)
    ; |1 - Case sensitive
    ; Return values .: Success - One of the following:
    ; |0 - Strings are equal
    ; |-1 - $s1 comes before $s2
    ; |1 - $s1 goes after $s2
    ; Failure - Returns -2 and Sets @Error:
    ; |1 - $s1 or $s2 is not a string
    ; |2 - $iCase is invalid
    ; Author ........: Erik Pilsits
    ; Modified.......:
    ; Remarks .......: Original algorithm by Dave Koelle
    ; Related .......: StringCompare
    ; Link ..........: http://www.davekoelle.com/alphanum.html
    ; Example .......: Yes
    ;
    ; ;==========================================================================================
    Func _NaturalCompare($s1, $s2, $iCase = 0)
    If (Not IsString($s1)) Or (Not IsString($s2)) Then Return SetError(1, 0, -2)
    If $iCase <> 0 And $iCase <> 1 Then Return SetError(2, 0, -2)

    Local $n = 0, $iLen = 1
    Local $s1chunk, $s2chunk

    While $n == 0 ; get next chunk
    ; STRING 1
    $iLen = 1
    If StringIsDigit(StringLeft($s1, 1)) Then
    ; chunk of digits
    For $i = 2 To StringLen($s1)
    If StringIsDigit(StringMid($s1, $i, 1)) Then
    $iLen += 1
    Else
    ExitLoop
    EndIf
    Next
    Else
    ; chunk of letters
    For $i = 2 To StringLen($s1)
    If Not StringIsDigit(StringMid($s1, $i, 1)) Then
    $iLen += 1
    Else
    ExitLoop
    EndIf
    Next
    EndIf
    $s1chunk = StringLeft($s1, $iLen)

    ; STRING 2
    $iLen = 1
    If StringIsDigit(StringLeft($s2, 1)) Then
    ; chunk of digits
    For $i = 2 To StringLen($s2)
    If StringIsDigit(StringMid($s2, $i, 1)) Then
    $iLen += 1
    Else
    ExitLoop
    EndIf
    Next
    Else
    ; chunk of letters
    For $i = 2 To StringLen($s2)
    If Not StringIsDigit(StringMid($s2, $i, 1)) Then
    $iLen += 1
    Else
    ExitLoop
    EndIf
    Next
    EndIf
    $s2chunk = StringLeft($s2, $iLen)

    ; ran out of chunks, strings are the same, return 0
    If $s1chunk == "" And $s2chunk == "" Then Return 0

    ; remove chunks from strings
    $s1 = StringMid($s1, StringLen($s1chunk) + 1)
    $s2 = StringMid($s2, StringLen($s2chunk) + 1)

    ; Case 1: both chunks contain letters
    If (Not StringIsDigit($s1chunk)) And (Not StringIsDigit($s2chunk)) Then
    $n = StringCompare($s1chunk, $s2chunk, $iCase)
    Else
    ; Case 2: both chunks contain numbers
    If StringIsDigit($s1chunk) And StringIsDigit($s2chunk) Then
    Local $i1chunk = Int($s1chunk)
    Local $i2chunk = Int($s2chunk)
    If $i1chunk > $i2chunk Then
    Return 1
    ElseIf $i1chunk < $i2chunk Then
    Return -1
    EndIf
    Else
    ; Case 3: one chunk has letters, the other has numbers; or one is empty
    ; if we get here, this should be the last and deciding test, so return the result
    Return StringCompare($s1chunk, $s2chunk, $iCase)
    EndIf
    EndIf
    WEnd

    Return $n
    EndFunc

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _ArrayNaturalSort
    ; Description ...: Sort a 1D or 2D array on a specific index using the quicksort/insertionsort algorithms.
    ; Syntax.........: _ArrayNaturalSort(ByRef $avArray[, $iDescending = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]])
    ; Parameters ....: $avArray - Array to sort
    ; $iDescending - [optional] If set to 1, sort descendingly
    ; $iStart - [optional] Index of array to start sorting at
    ; $iEnd - [optional] Index of array to stop sorting at
    ; $iSubItem - [optional] Sub-index to sort on in 2D arrays
    ; Return values .: Success - 1
    ; Failure - 0, sets @error:
    ; |1 - $avArray is not an array
    ; |2 - $iStart is greater than $iEnd
    ; |3 - $iSubItem is greater than subitem count
    ; |4 - $avArray has too many dimensions
    ; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
    ; Modified.......: LazyCoder - added $iSubItem option, Tylo - implemented stable QuickSort algo, Jos van der Zande - changed logic to correctly Sort arrays with mixed Values and Strings, Ultima - major optimization, code cleanup, removed $i_Dim parameter
    ; Prog@ndy - natural sort
    ; Remarks .......:
    ; Related .......:
    ; Link ..........;
    ; Example .......; Yes
    ; ===============================================================================================================================
    Func _ArrayNaturalSort(ByRef $avArray, $iDescending = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)

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

    Local $iUBound = UBound($avArray) - 1

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

    ; Bounds checking
    If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
    If $iStart < 0 Then $iStart = 0
    If $iStart > $iEnd Then Return SetError(2, 0, 0)

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

    ; Sort
    Switch UBound($avArray, 0)
    Case 1
    __ArrayNaturalQuickSort1D($avArray, $iStart, $iEnd)
    If $iDescending Then _ArrayReverse($avArray, $iStart, $iEnd)
    Case 2
    Local $iSubMax = UBound($avArray, 2) - 1
    If $iSubItem > $iSubMax Then Return SetError(3, 0, 0)

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

    If $iDescending Then
    $iDescending = -1
    Else
    $iDescending = 1
    EndIf

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

    __ArrayNaturalQuickSort2D($avArray, $iDescending, $iStart, $iEnd, $iSubItem, $iSubMax)
    Case Else
    Return SetError(4, 0, 0)
    EndSwitch

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

    Return 1
    EndFunc ;==>_ArrayNaturalSort

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

    ; #INTERNAL_USE_ONLY#============================================================================================================
    ; Name...........: __ArrayNaturalQuickSort1D
    ; Description ...: Helper function for sorting 1D arrays
    ; Syntax.........: __ArrayNaturalQuickSort1D(ByRef $avArray, ByRef $iStart, ByRef $iEnd)
    ; Parameters ....: $avArray - Array to sort
    ; $iStart - Index of array to start sorting at
    ; $iEnd - Index of array to stop sorting at
    ; Return values .: None
    ; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
    ; Modified.......: Prog@ndy - natural sort
    ; Remarks .......: For Internal Use Only
    ; Related .......:
    ; Link ..........;
    ; Example .......;
    ; ===============================================================================================================================
    Func __ArrayNaturalQuickSort1D(ByRef $avArray, ByRef $iStart, ByRef $iEnd)
    If $iEnd <= $iStart Then Return

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

    Local $vTmp

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

    ; InsertionSort (faster for smaller segments)
    If ($iEnd - $iStart) < 15 Then
    Local $i, $j, $vCur
    For $i = $iStart + 1 To $iEnd
    $vTmp = $avArray[$i]

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

    For $j = $i - 1 To $iStart Step -1
    If (_NaturalCompare($vTmp, $avArray[$j], 1) >= 0) Then ExitLoop
    $avArray[$j + 1] = $avArray[$j]
    Next

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

    $avArray[$j + 1] = $vTmp
    Next
    Return
    EndIf

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

    ; QuickSort
    Local $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)]
    Do
    While (_NaturalCompare($avArray[$L], $vPivot, 1) < 0)
    $L += 1
    WEnd
    While (_NaturalCompare($avArray[$R], $vPivot, 1) > 0)
    $R -= 1
    WEnd

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

    ; Swap
    If $L <= $R Then
    $vTmp = $avArray[$L]
    $avArray[$L] = $avArray[$R]
    $avArray[$R] = $vTmp
    $L += 1
    $R -= 1
    EndIf
    Until $L > $R

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

    __ArrayNaturalQuickSort1D($avArray, $iStart, $R)
    __ArrayNaturalQuickSort1D($avArray, $L, $iEnd)
    EndFunc ;==>__ArrayNaturalQuickSort1D

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

    ; #INTERNAL_USE_ONLY#============================================================================================================
    ; Name...........: __ArrayNaturalQuickSort2D
    ; Description ...: Helper function for sorting 2D arrays
    ; Syntax.........: __ArrayNaturalQuickSort2D(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
    ; Parameters ....: $avArray - Array to sort
    ; $iStep - Step size (should be 1 to sort ascending, -1 to sort descending!)
    ; $iStart - Index of array to start sorting at
    ; $iEnd - Index of array to stop sorting at
    ; $iSubItem - Sub-index to sort on in 2D arrays
    ; $iSubMax - Maximum sub-index that array has
    ; Return values .: None
    ; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
    ; Modified.......: Prog@ndy - natural sort
    ; Remarks .......: For Internal Use Only
    ; Related .......:
    ; Link ..........;
    ; Example .......;
    ; ===============================================================================================================================
    Func __ArrayNaturalQuickSort2D(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
    If $iEnd <= $iStart Then Return

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

    ; QuickSort
    Local $i, $vTmp, $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)][$iSubItem]
    Do

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

    While ($iStep * _NaturalCompare($avArray[$L][$iSubItem], $vPivot, 1) < 0)
    $L += 1
    WEnd
    While ($iStep * _NaturalCompare($avArray[$R][$iSubItem], $vPivot, 1) > 0)
    $R -= 1
    WEnd

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

    ; Swap
    If $L <= $R Then
    For $i = 0 To $iSubMax
    $vTmp = $avArray[$L][$i]
    $avArray[$L][$i] = $avArray[$R][$i]
    $avArray[$R][$i] = $vTmp
    Next
    $L += 1
    $R -= 1
    EndIf
    Until $L > $R

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

    __ArrayNaturalQuickSort2D($avArray, $iStep, $iStart, $R, $iSubItem, $iSubMax)
    __ArrayNaturalQuickSort2D($avArray, $iStep, $L, $iEnd, $iSubItem, $iSubMax)
    EndFunc ;==>__ArrayNaturalQuickSort2D

    [/autoit]


    //Edit: Beispeil:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    Global $array[20]
    For $i = 0 To 19
    $array[$i] = 'Beispiel ' & $i*Random(1,5,1)
    Next
    _ArraySort($array)
    _ArrayDisplay($array, 'Array mit _ArraySort')
    _ArrayNaturalSort($array)
    _ArrayDisplay($array, 'Array mit _ArrayNaturalSort')

    [/autoit]
  • Die gab es vorher schon, aber die ist beim Update des englischen Forums zerstört worden, da die geshi-Umsetzung zuvor nich ganz OK war.