_StringFormatSimple (extrem einfacher, geschwindigkeitsoptimierter Ersatz)

  • Auch wenn ich AutoIt nicht für schnelle, komplexe Programme einsetze - dafür ist ja nun wirklich nicht gemacht - hier mal eine winzige Optmierung:

    Ok erstmal vorweg, der Name paßt nicht wirklich, aber da ich StringFormat in 95% aller Fälle so einsetze:

    [autoit]

    StringFormat("Das ist ein %s usw. mit %i Wörtern", "Text", 6)

    [/autoit]


    da es einfach übersichtlicher ist als den String mit zig & zu zerhacken, hat diese "Funktion" eben diesen Namen.

    Extremer Nachteil dabei:
    StringFormat ist extrem langsam. Zum Vergleich:

    Spoiler anzeigen
    [autoit]


    $iEnde = 1000

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    $bla = "test" & "test" & "test"
    Next
    ConsoleWrite( TimerDiff($timer) & @CRLF)

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    $bla = StringFormat("%s %s %s", "test", "test", "test")
    Next
    ConsoleWrite( TimerDiff($timer) & @CRLF)

    [/autoit]


    erste Version ca. 7ms, Version mit Stringformat ca. 360ms! Wobei die Differenz je nach Größe des eigentlichen Strings natürlich zunimmt.

    Was nun folgt sind die 2 "Funktionen", deren Erfindungshöhe auf 0-Niveau sind, aber für meinen Hauptanwendungszweck ca. 2,5-4mal schneller als StringFormat:

    Spoiler anzeigen
    [autoit]

    Func _StringFormatSimple(ByRef $s, ByRef $a)
    For $i = 1 To $a[0]
    $s = StringReplace($s,"%s"&$i,$a[$i])
    Next
    EndFunc
    ; Version 2
    Func _StringFormatSimple2(ByRef $s, ByRef $a)
    For $i = 1 To $a[0]
    $s = StringReplace($s,"%s",$a[$i],1,2)
    Next
    EndFunc

    [/autoit]

    genau - die Funktionen machen nichts weiter als "%s" durch ein Element des übergebenen Array zu ersetzen,
    Die erste Version ersetzt %sn (erstes Element %s1) global durch das Vorkommen des Platzhalters, die zweite nur das erste Vorkommen des Platzhalters. Wobei die erste Version wesentlich langsamer ist wie die zweite.

    Ein Parameter zum wechseln des Modi würde das Ganze wieder langsamer machen, deswegen zwei Funktionen.
    Auch ein UBound würde um ca. 5% bremsen, deswegen die Übergabe per Array, auch wenn gemischte Datentypen dort auch nicht optimal sind.

    Der Aufruf ist etwas ungewöhlich:

    Spoiler anzeigen
    [autoit]

    $var[0] = 3
    $var[1] = "test1"
    $var[2] = "test2"
    $var[3] = "test3"
    $sString = "%s %s %s"
    _StringFormatSimple4($sString, $var)

    [/autoit]

    Also mehr zur Info als Funktion, aber vielleicht kann ja jemand damit was anfangen :)

  • Wusste nicht, dass StringFormat so langsam ist. :huh:
    Bei der Verwendung für Floats mit begrenzten Nachkommastellen geht's aber viel schneller. :huh:

    Hab mich an einer Version für dich versucht, die bei mir noch ein bisschen schneller ist ;)

    Spoiler anzeigen
    [autoit]

    ; Version 2
    Func _StringFormatSimple2(ByRef $s, ByRef $a)
    For $i = 1 To $a[0]
    $s = StringReplace($s,"%s",$a[$i],1,2)
    Next
    EndFunc

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

    ; Version funkey
    Func _StringFormatSimple3(ByRef $s, ByRef $a)
    Local $new = ""
    For $i = 1 To $a[0] -1
    $new &= $a[$i] & $s
    Next
    Return $new & $a[$i]
    EndFunc

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

    Global $var[4]
    $var[0] = 3
    $var[1] = "test1"
    $var[2] = "test2"
    $var[3] = "test3"
    $sString = "%s %s %s"

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

    $iEnde = 1000

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    $bla = "test1" & " " & "test2" & " " & "test3"
    Next
    ConsoleWrite( $bla & " " & TimerDiff($timer) & @CRLF)

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    $bla = StringFormat("%s %s %s", "test1", "test2", "test3")
    Next
    ConsoleWrite( $bla & " " & TimerDiff($timer) & @CRLF)

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    _StringFormatSimple2($sString, $var)
    Next
    ConsoleWrite( $sString & " " & TimerDiff($timer) & @CRLF)

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

    $sString = ' '
    $timer = TimerInit()
    For $i = 0 To $iEnde
    $bla = _StringFormatSimple3($sString, $var)
    Next
    ConsoleWrite( $bla & " " & TimerDiff($timer) & @CRLF)

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    $bla = StringFormat("%.2f %.2f %.2f", 9.12345, 17.1239734, 13)
    Next
    ConsoleWrite( $bla & " " & TimerDiff($timer) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • Danke - klar ist es schneller :) - kommt auch nicht das Gleiche dabei heraus:

    Spoiler anzeigen
    [autoit]

    ; Version 2
    Func _StringFormatSimple2(ByRef $s, ByRef $a)
    For $i = 1 To $a[0]
    $s = StringReplace($s,"%s",$a[$i],1,2)
    Next
    EndFunc

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

    ; Version funkey
    Func _StringFormatSimple3(ByRef $s, ByRef $a)
    Local $new = ""
    For $i = 1 To $a[0] -1
    $new &= $a[$i] & $s
    Next
    Return $new & $a[$i]
    EndFunc

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

    Global $var[4]
    $var[0] = 3
    $var[1] = "test1"
    $var[2] = "test2"
    $var[3] = "test3"

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

    $iEnde = 1000

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    $sString = "%s %s %s"
    _StringFormatSimple2($sString, $var)
    Next
    ConsoleWrite( $sString & " " & TimerDiff($timer) & @CRLF)

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

    $timer = TimerInit()
    For $i = 0 To $iEnde
    $sString = "%s %s %s"
    $bla = _StringFormatSimple3($sString, $var)
    Next
    ConsoleWrite( $bla & " " & TimerDiff($timer) & @CRLF)

    [/autoit]

    Mein Beispiel war in den "Testläufen" etwas ungenau, ich möchte ja nicht einfach ein Array zusammenbauen, sonder gezielt Platzhalter durch Variablen ersetzen, wie eben in:
    "Das ist ein %s usw. mit %s Wörtern."
    sonst könnt ich mir den Aufwand sparen.

    Das mit den floats ist allerdings schön und verwunderlich - bring mir aber leider nichts.

  • Den habe ich gesehen und der ist auch das Problem, da es ein leerer String ist, du arbeitest einfach ohne Platzhalter und setzt das Array zusammen.

    Probier mal das:

    Spoiler anzeigen
    [autoit]

    Global $var[4]
    $var[0] = 3
    $var[1] = "test1"
    $var[2] = "test2"
    $var[3] = "test3"

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

    $sString = "Das ist das erste Wort %s, das zweite %s und das dritte %s"

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

    _StringFormatSimple2($sString, $var)
    ConsoleWrite( $sString & @CRLF)

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

    $sString = "Das ist das erste Wort %s, das zweite %s und das dritte %s"

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

    $sString = _StringFormatSimple3($sString, $var)
    ConsoleWrite( $sString & @CRLF)

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

    ; Version 2
    Func _StringFormatSimple2(ByRef $s, ByRef $a)
    For $i = 1 To $a[0]
    $s = StringReplace($s,"%s",$a[$i],1,2)
    Next
    EndFunc

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

    ; Version funkey
    Func _StringFormatSimple3(ByRef $s, ByRef $a)
    Local $new = ""
    For $i = 1 To $a[0] -1
    $new &= $a[$i] & $s
    Next
    Return $new & $a[$i]
    EndFunc

    [/autoit]