Arrays "freigeben"

  • Hey,


    ich hätte mal eine "allgemeine" Frage zu AutoIt. Ich habe zum "Spaß" mal _ArrayDelete() in einfach und für 1D-Arrays gebaut und wollte, weil ich eh immer ein "Temp-Array" brauche, einfach ein ganz neues Array "bauen", anstatt ReDim() zu nutzen^^...


    Wenn Arrays lokal sind, "leben" sie ja auch nur, solange die Funktion genutzt wird, dann wird der Speicher wieder frei gegeben?
    Und wenn ich ein altes Array überschreiben lasse, ist das alte auch im "Nirwana", oder?!


    Func _ArrayDel($aArray, $iIndex)
    If Not IsArray($aArray) Then Return 0
    Local $iSize = UBound($aArray) - 1
    If $iSize <= 0 Then Return 0
    Local $aArrayNew[$iSize]


    For $i = 0 To $iIndex - 1
    $aArrayNew[$i] = $aArray[$i]
    Next


    For $i = $iIndex + 1 To $iSize
    $aArrayNew[$i - 1] = $aArray[$i]
    Next


    Return $aArrayNew
    EndFunc


    So hatte ich mir das gedacht... Wo ist der Vorteil von "ReDim" und der Variante, wie das in der offiziellen UDF gemacht wird?^^ ReDim ist ja auch sehr rechenintensiv, müsste das so nicht eig. auch schneller sein?!^^ Was übersehe ich :P?


    Ich habe mal von BugFix gelesen, wenn man ne UDF macht, sollte man ohne Includes arbeiten, sonst ist es unsauber xD... Und da ich grade ne _ArrayFilter/_ArrayClean (wie auch immer ich das dann nenne) - Funktion mache, wollte ich halt ein paar Funktionen "nachbauen"^^...



    Bin da auch gern für Verbesserungsvorschläge offen, wobei ich das für 2D-Arrays eh nochmal anpassen müsste, denke ich :P...



    LG,
    Aca

    Einmal editiert, zuletzt von Acanis ()

  • Wo ist der Vorteil von "ReDim" und der Variante, wie das in der offiziellen UDF gemacht wird? ReDim ist ja auch sehr rechenintensiv, müsste das so nicht eig. auch schneller sein?! Was übersehe ich ?

    ReDim ist nicht wirklich rechenintensiv sondern der eventuell entstehende Kopieraufwand benötigt unter Umständen viel Zeit.
    Machen wir es doch mal an einem Beispiel:
    Im Speicher liegt ein Array mit 1000 Elementen. Dahinter ist im Speicher kein Platz mehr weil da ein anderer Wert steht.
    Nun soll das Array um 1 Element vergrößert werden (per ReDim)
    Da dahinter kein Platz mehr ist muss nun das gesamte Array Element für Element in einen Speicherbereich kopiert werden welcher Platz für 1001 Elemente bietet.
    Das frisst Zeit.
    Andersherum: Das Array soll um ein Element gekürzt werden: HIer gibt es natürlich keine Platzprobleme.
    Das Array bleibt an der selben Stelle nur dessen Größenangabe wird offiziell geändert - mehr nicht. Das geht also verdammt fix.
    Pauschal ist ein ReDim also nicht unbedingt langsam.


    Nun zu deinem Code und wie er sich im Vergleich zur offiziellen UDF-Funktion schlägt:
    Was passiert bei dir?:

    • Ein Array wird als Kopie übergeben (da es nicht mit ByRef übergeben wird). Das heißt das Array wird einmal 1:1 komplett Element für Element kopiert - das dauert.
    • Nun erstellst du ein neues Array und kopierst die Inhalte des Arrays Element für Element bis auf das eine Element in das neue Array.
    • Zusammengefasst: Wenn dein Array n-Elemente hat führst du 2*n-1 Kopien durch.


    Was passiert hingegen bei der offiziellen UDF?:

    • Ein Verweis auf ein Array wird übergeben - es wird nichts kopiert (ByRef)
    • Ab dem Element welches gelöscht wird jedes Element nur um eine einzige Stelle nach vorn verschoben.
    • per ReDim wird das letzte Element abgeschnitten


    Im Extremfall (das letzte Element soll gelöscht werden) hast du 2*n-1 Elementkopien und die UDF-Funktion hingegen nur ein einziges ReDim was in dem Fall verdammt flott geht.



    Ich habe mal von BugFix gelesen, wenn man ne UDF macht, sollte man ohne Includes arbeiten, sonst ist es unsauber xD

    Ich denke er wird es sicherlich in einem gewissen Zusammenhang gemeint haben.
    Die Standard-UDFs sind natürlich o.k. denn dafür wurden sie ja geschrieben.
    Es ist natürlich nie so gedacht gewesen das man, obwohl die Funktionen alle zur Verfügung stehen, für die eigene Verwendung alles nochmal selbst schreiben muss.

  • Ah, okey, danke :)...
    Beim Verkleinern ist ReDim also auf jeden Fall die bessere Wahl.


    Trotzdem muss ich, da ich ja nicht das letzte Element abschneide, muss ich ja ein Hilfsarray kopieren. (Aber die UDF-Methode scheint ja echt ganz gut durchdacht zu sein *hmpf* :D)


    Mit ByRef kann ich beim Erzeugen des Hilfs-Arrays also Rechenleistung sparen? Ala Beispiel:
    Func swap(ByRef $a, ByRef $b) ;swap the contents of two variables
    Local $t
    $t = $a
    $a = $b
    $b = $t
    EndFunc ;==>swap


    Ich schau mir auf jeden Fall die UDF-Funktion nochmal an, danke schon mal für die Aufklärung :D!



    LG,
    Aca


  • Beim Verkleinern ist ReDim also auf jeden Fall die bessere Wahl.
    Trotzdem muss ich, da ich ja nicht das letzte Element abschneide, muss ich ja ein Hilfsarray kopieren.


    In der Regel sind die nativen Funktionen und Standard-UDFs besser, solange sie genau das tun, für was du sie brauchst.
    Bei der UDF wird nicht in ein Hilfsarray kopiert.
    Da wird einfach ab dem zu löschenden index alles um einen verschoben und danach das array um 1 verkleinert.

  • Trotzdem muss ich, da ich ja nicht das letzte Element abschneide, muss ich ja ein Hilfsarray kopieren.

    Nicht wenn du es wie in der UDF machst.
    Dann nimmst du einfach direkt das originale Array und verschiebst nur die Elemente nach dem Element was gelöscht werden soll um eins nach vorn.
    So ist kein Hilfsarray notwendig.


    Mit ByRef kann ich beim Erzeugen des Hilfs-Arrays also Rechenleistung sparen?

    Es gibt zwei Arten Variablen an Funktionen als Parameter zu übergeben:

    • By Value: Hierbei wird eine lokale Variable erstellt die den Inhalt des übergebenen Parameters erhalten wird. Änderungen an dieser lokalen Variable haben keine Auswirkungen auf die Variable außerhalb der Funktion welche als Parameter übergeben wurde.
    • By Reference: Hierbei wird ein Verweis auf die Variable übergeben. Vereinfacht gesagt ist es ein und die selbe Variable. Änderungen haben also auch Auswirkungen auf die äußere Variable.

    Gerade bei Arrays oder anderen großen Datenstrukturen ist die Übergabe per ByRef also flotter da hierbei das Kopieren wegfällt.

  • Und "By Value" ist "Standard", wenn man Funktionen mit Parametern macht?


    Und dann kann man ja, wenn man ein Array "bearbeitet", wie hier beim Filtern, eig. immer besser mit ByRef arbeiten, hmmm :)

  • Und "By Value" ist "Standard", wenn man Funktionen mit Parametern macht?


    Und dann kann man ja, wenn man ein Array "bearbeitet", wie hier beim Filtern, eig. immer besser mit ByRef arbeiten, hmmm :)


    Exakt. Es gibt eine kleine Ausnahme bei DLLStructs, diese kann man sozusagen nur ByRef übergeben. (Nicht wirklich, aber es macht keinen wirklichen Unterschied. Die AutoIt-Variable enthält die Struktur-Definition und einen Pointer auf die Struktur im Speicher. Nun ist es egal, ob diese Infos referenziert oder kopiert werden, der Pointer im Speicher bleibt der gleiche.)

  • Alles klar, danke^^... Habe das gleich mal übernommen und dazu noch nen Bubblesort für Arrays umgesetzt^^



    Und die Array-Filter:



    Wobei ich bei der sehr guten ArrayUnique von UEZ auch gesehen habe, dass man eig. 1D und 2D gut in eine Func packen kann, mach ich vllt. auch noch :P...



    Und noch die Filterfunktion für 2D-Arrays machen :D...


    Vielleicht brauchts ja mal wieder wer^^.



    LG,
    Aca


    PS: Hab den Thread mal auf erledigt gesetzt, hat mir geholfen und hab das nu besser verstanden, danke nochmal :D!