Array nach der Häufigkeit des Inhaltes sortieren

  • Hmn, erstmal vorweg: Die Überschrift ist bestimmt nicht am besten gewählt, aber naja :/


    Vor längeren hatte fredowsky eine Funktion gebraucht, die das Array nach der Häufigkeit seines Inhaltes sortiert.
    Ich habe die Funktion immernoch auf der Festplatte hier rumliegen und würde sie euch gerne zur Verfügung stellen.

    Sicher gibt es flexiblere möglichkeiten (und vor allem schnellere), aber ich hab diese nicht groß ausgebaut.


    Die Funktion kann nur ein 1D-Array sortieren.
    Ab 1000 Einträgen verbraucht die Funktion mind. 2-3 Sekunden an Zeit.


    Wenn jemand die Funktion ausbauen will, kann er/sie das tun. Die Funktionsbeschreibung habe ich einfach auf die schnelle dahin geschrieben.


    Und hier die Funktion:

    Spoiler anzeigen
    [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name ..........: _Sort
    ; Description ...: Sortiert ein Array nach der Häufigkeit seiner Einträge.
    ; Syntax ........: _Sort($Array[, $flag = True])
    ; Parameters ....: $Array - Das zu sortierende Array.
    ; $flag - [optional] True : Absteigend sortieren.
    ; False: Aufsteigend sortieren.
    ; Return values .: Das sortierte Array.
    ; Author ........:
    ; Modified ......:
    ; Remarks .......:
    ; Related .......:
    ; Link ..........:
    ; Example .......: No
    ; ===============================================================================================================================
    Func _Sort($Array, $flag = True)
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    Local $UBound = UBound($Array, 1) - 1
    Local $count = 0
    Local $Save[$UBound + 1][2]
    Local $Sort[$UBound + 1]
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    For $a = 0 To $UBound
    For $b = 0 To $UBound
    If $Save[$b][1] = '' Then
    $Save[$b][0] = $Array[$a]
    $Save[$b][1] = 1
    $b = $UBound
    ElseIf $Save[$b][0] = $Array[$a] Then
    $Save[$b][1] += 1
    $b = $UBound
    EndIf
    Next
    Next
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    For $c = 0 To $UBound
    For $d = 0 To $UBound
    If $Save[$d][1] = $c + 1 Then
    For $e = 0 To $c
    $Sort[$e + $count] = $Save[$d][0]
    Next
    $count += $Save[$d][1]
    EndIf
    Next
    Next
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    If $flag Then _Invertieren($Sort)
    Return $Sort
    EndFunc ;==>_Sort

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

    ; #FUNCTION# ====================================================================================================================
    ; Name ..........: _Invertieren
    ; Description ...: Dreht die Inhalte des Array's um.
    ; Syntax ........: _Invertieren(Byref $Array)
    ; Parameters ....: $Array - [in/out] Das zu umkehrende Array.
    ; Return values .: None
    ; Author ........:
    ; Modified ......:
    ; Remarks .......:
    ; Related .......:
    ; Link ..........:
    ; Example .......: No
    ; ===============================================================================================================================
    Func _Invertieren(ByRef $Array)
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    Local $UBound = UBound($Array, 1) - 1
    Local $count = 0
    Local $Save[$UBound + 1]
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    For $a = 0 To $UBound
    $Save[$a] = $Array[$a]
    Next
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    For $b = $UBound To 0 Step -1
    $Array[$b] = $Save[$count]
    $count += 1
    Next
    ; ++++++ ++++++ ++++++ ++++++ ++++++ ++++++
    EndFunc ;==>_Invertieren

    [/autoit]


    Will ich mal hoffen, dass sie vllt. Dem einem oder andere hilft.

    Einmal editiert, zuletzt von Yjuq (8. Oktober 2012 um 15:46)

  • macht deine Funktion _Invertieren nicht das gleiche wie _ArrayReverse?

    "Je mehr Käse, desto mehr Löcher; je mehr Löcher, desto weniger Käse. Ergo: Je mehr Käse, desto weniger Käse. 8| "
    "Programmers never die: they just GOSUB without RETURN"
    "I tried to change the world but I couldn't find the source code."

  • Ist ja auch nicht schlimm.

    ist es auch nicht ;)
    Ich würde an solchen Stellen halt auf bereits vorhandene Funktionen zurückgreifen, deshalb meint ich nur..

    "Je mehr Käse, desto mehr Löcher; je mehr Löcher, desto weniger Käse. Ergo: Je mehr Käse, desto weniger Käse. 8| "
    "Programmers never die: they just GOSUB without RETURN"
    "I tried to change the world but I couldn't find the source code."

    • Offizieller Beitrag

    Als Tipp:
    Das Array ByRef übergeben, sonst wird es völlig unnütz beim Aufruf der Funktion kopiert.

    Ein 1D-Array nach Häufigkeit von Einträgen zu sortieren macht aber wenig Sinn. Da ja kein Partnerwert (wie bei einer Schlüssel-Wert-Verknüpfung) existiert, ist es doch völlig ohne Belang wo die Werte im Array abgelegt sind. Schlimmer noch: durch den Sortiervorgang wird auch noch die Verknüpfung Index-Wert zerrissen.
    Es gibt sicher Einsatzvarianten, wo das Sinn macht. Aber in der Regel ist man dort mit einem anderen Datentyp besser bedient.

  • Da mir langweilig ist und ich mal wieder was mit AutoIt machen wollt, hier mal wie man das mit Scripting.Dictionary lösen könnte:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    Dim $aArray[10000]
    For $iI = 0 To 9999 ; Array befüllen
    $aArray[$iI] = Chr(Random(65, 122, 1))
    Next

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

    $aSort = _Sort($aArray, 1)
    _ArrayDisplay($aSort)

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

    Func _Sort(ByRef $aArray, $iDescending = 0)
    Local $oCompareList = ObjCreate("Scripting.Dictionary")
    For $iI = 0 To UBound($aArray)-1 ; Keys & Items in das Dictionary eintragen
    If $oCompareList.Exists($aArray[$iI]) Then
    $oCompareList.Item($aArray[$iI]) = $oCompareList.Item($aArray[$iI]) + 1
    Else
    $oCompareList.Add($aArray[$iI], 1)
    EndIf
    Next
    Dim $aCompare[$oCompareList.Count][2], $aKeys = $oCompareList.Keys
    $iCount = 0
    For $sKey In $oCompareList.Keys ; Keys & Items in ein 2D-Array schreiben
    $aCompare[$iCount][0] = $sKey
    $aCompare[$iCount][1] = $oCompareList.Item($sKey)
    $iCount += 1
    Next
    _ArraySort($aCompare, $iDescending, 0, 0, 1)
    Return $aCompare
    EndFunc

    [/autoit]
    Zitat

    Es gibt sicher Einsatzvarianten, wo das Sinn macht.


    Man könnte z.B. die Buchstabenhäufigkeit messen:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    $sString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non convallis sem." & _
    "Morbi pharetra diam vitae massa aliquet ac ultrices odio sagittis." & _
    "Vivamus tempus dapibus risus, vitae mattis diam laoreet id." & _
    "Donec egestas malesuada odio, eget varius sem interdum at. Duis lobortis tristique augue id interdum." & _
    "Maecenas bibendum erat eget odio placerat mollis. Praesent aliquet congue felis, ac mattis libero ornare aliquet." & _
    "Vestibulum ultrices placerat dui nec auctor."
    $aArray = StringSplit($sString, "", 2)

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

    $aSort = _Sort($aArray, 1)
    _ArrayDisplay($aSort)

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

    Func _Sort(ByRef $aArray, $iDescending = 0)
    Local $oCompareList = ObjCreate("Scripting.Dictionary")
    For $iI = 0 To UBound($aArray)-1 ; Keys & Items in das Dictionary eintragen
    If $oCompareList.Exists($aArray[$iI]) Then
    $oCompareList.Item($aArray[$iI]) = $oCompareList.Item($aArray[$iI]) + 1
    Else
    $oCompareList.Add($aArray[$iI], 1)
    EndIf
    Next
    Dim $aCompare[$oCompareList.Count][2], $aKeys = $oCompareList.Keys
    $iCount = 0
    For $sKey In $oCompareList.Keys ; Keys & Items in ein 2D-Array schreiben
    $aCompare[$iCount][0] = $sKey
    $aCompare[$iCount][1] = $oCompareList.Item($sKey)
    $iCount += 1
    Next
    _ArraySort($aCompare, $iDescending, 0, 0, 1)
    Return $aCompare
    EndFunc

    [/autoit]

    Edit: Vielleicht meinte BugFix mit "Aber in der Regel ist man dort mit einem anderen Datentyp besser bedient. " so etwas.

    Zitat

    You just keep on trying 'till you run out of cake. ;)


    [STEAM] Source UDF

    Einmal editiert, zuletzt von K4z (8. Oktober 2012 um 18:16)