Bitte Forenregeln lesen! Wir unterstützen hier keine Bots!
[Thread closed]
Beiträge von Oscar
-
-
Falls das zu viele Dateien sind, kannst Du sie ja vorher packen (z.B. als ZIP) und dann mit FileInstall einbinden.
-
Ich sehe AutoIt als Programmiersprache an. Ist letztendlich aber eine Definitionsfrage...
Und warum sollte man nicht auch ein Script optimieren (im ms-Berech) dürfen? Wenn ein bestimmter Befehl einige tausend mal ausgeführt wird, dann machen sich auch Millisekunden bemerkbar.
Ich habe auch kein Problem damit, zeitkritische Dinge in einer anderen Programmiersprache (z.B. mittels dll) einzubinden. Dem Anwender ist das sowas von egal, in welcher Sprache ein Programm geschrieben ist, solange das Programm genau das macht, was er davon erwartet.
Und der Vorteil für mich ist einfach, dass ich in AutoIt schnell zu einem funktionierenden Programm komme. Meine Programme gebe ich meist als ZIP-Archiv an andere weiter. Da schaffen auch DAUs die "Installation". Für die Super-DAUs könnte man ja auch noch ein Installationsskript erstellen, das war aber bisher nicht nötig.
Soll jeder sehen, wie er will. Ich mag AutoIt und ich freue mich, wenn ich ein Problem mit AutoIt lösen kann.
Programmieren mit AutoIt ist ein Hobby von mir und da kommt es im wesentlichen darauf an, dass es Spass macht.
-
Das mit dem "besseren MP3-Player" lasse ich mir mal durch den Kopf gehen.
Erstmal gibt es jetzt eine neue Version (siehe Post #1), in der ich den Sourcecode etwas aufgeräumt und ein paar kleine Details hinzugefügt habe. -
Neue Version (siehe Post #1).
Jetzt mit Ähnlichkeitssuche. -
Ach, ich bin immer noch ganz begeistert von der Funktion (Bernd, Du solltest sie in einen extra Thread packen, vielleicht in Skripte, damit man sie bei Bedarf wiederfindet).
Die Funktion in AutoIt ist ja nicht schlecht, aber wenn es auf Geschwindigkeit ankommt, dann ist die C-Variante die bessere Wahl (ca. 1000 mal schneller).
Ich habe meine Testfunktion gerade mal mit verschiedenen Werten laufen lassen. Ganz erstaunlich, was da alles gefunden wird.
Es gibt bald eine neue Version vom MP3-Double-Finder.

-
Ok, die StringTrimLeft ist auch bei mir die schnellste Variante. Allerdings wirklich nur ein Tick, aber egal, jede gesparte Millisekunde wird mitgenommen.
Wobei ich das mit CaseSensitive nicht verstehe, denn in der Hilfe steht: "2 = not case sensitive, using a basic/faster comparison". Sollte dann nicht die "2" am schnellsten sein?!
-
Oh, mein Lieblingspattern (für StringRegExpReplace) zum extrahieren des Dateinamens aus einer Pfadangabe war immer:
[autoit]$string = StringRegExpReplace($sPath, '.+\\(.+)', '$1')
[/autoit]
[autoit]
Jetzt musste ich feststellen, dass es eine viel schnellere Methode gibt:
[/autoit]
$sPath = @AutoItExe
$iTimer = TimerInit()
$string = StringRegExpReplace($sPath, '.+\\(.+)', '$1')
ConsoleWrite('Mit RegExpRep: ' & TimerDiff($iTimer) & @CR)
$iTimer = TimerInit()
$string = StringMid($sPath, StringInStr($sPath, '\', 2, -1) + 1)
ConsoleWrite('Mit StringMid: ' & TimerDiff($iTimer) & @CR)
Die StringMid/StringInStr-Version ist bei mir fast 4mal schneller.
Meistens spielt das ja keine so große Rolle, aber bei meinem aktuellen Projekt ist das schon entscheidend.Nur als kleinen Tip für "Optimierungswütige"!

-
Wow! Bernd, das ist so genial!
Ich hab's gerade mal getestet. Mit der Funktion schafft mein Rechner eine (manchmal auch zwei) der äußeren Schleifendurchläufe in einer Sekunde (bei reinem AutoIt: 15 Minuten).
Das ist der Wahnsinn. Jetzt kann ich diese "unscharfe" Suche doch noch einbauen. Das würde zwar trotzdem noch lange dauern (ca. 2 Stunden insgesamt), aber das finde ich noch akzeptabel.Vielen, vielen Dank!

-
Äeh...das ist das gleiche Script, was ich oben schon gepostet habe.
Vom Prinzip her, ist das Script klasse, aber leider ist das in AutoIt zu langsam. -
Naja, ich hab keinen C-Compiler installiert (und auch keine Ahnung wie man den Sourcecode compiliert). Von daher wäre es als DLL schon gut, aber interessieren würde mich auch der Sourcecode.
Vielleicht sollte ich mich doch noch mal eingehend mit C beschäftigen... -
Ich kann leider kein C++.
Wenn Du das machen kannst, könnte ich zumindest mal testen, wieviel schneller das dann ist.
-
Das ist ja das Problem. Es soll halt Ähnlichkeiten aufzeigen und da müsste auch das Beispiel von Dir auftauchen.
Kennt vielleicht jemand ein Programm in C(++), wo ein Stringvergleich mittels Levenshtein-Distanz möglich ist? Vielleicht als DLL zum benutzen mit AutoIt. -
Ich habe auch mal so eine Uhr gemacht: Digitaluhr
Kannst Dir ja einige Ideen abschauen. -
Es geht um mein Programm "MP3-Double-Finder".
Mal ein Beispiel:
String1 = Bruce Springsteen - 57 Channels (And Nothin' On).mp3
String2 = Bruce Springsten - 57 Channels (And Nothing On).mp3Man sieht ja auf den ersten Blick, dass es sich dabei um die gleichen Lieder handelt, aber wie mache ich das programmtechnisch?
Ich möchte nun, dass die Funktion einen Wert ausgibt, wie ähnlich sich die beiden Strings sind (z.B. in Prozent).
Nun habe ich hier im Forum eine Funktion gefunden, die genau das macht:Spoiler anzeigen
[autoit]
[/autoit] [autoit][/autoit] [autoit]
; FaTolStrComp00.AU3 fehlertoleranter Zeichenkettenvergleich für AutoIT3
; basiert auf der Levenshtein-Distanz, siehe dazu http://de.wikipedia.org/wiki/Levenshtein-Distanz
; Lutz Müller, FH Köln Campus Gummersbach (uuchip http://www.autoit.de)
; Inhalt
; min3($a,$b,$c) - Minimum aus drei Werten wird zurückgegben
; LevenshteinDistance($s, $t) - Gibt Levenshteinabstand der beide Zeichenketten zurück
; Für die Levenshtein-Distanz gelten einige obere und untere Schranken:
; * sie beträgt mindestens den Unterschied der Längen beider Strings
; * sie beträgt höchstens die Länge des längeren Strings
; * sie ist dann und nur dann 0, wenn beide Strings identisch sind
; CompTstr($s, $t) - toleranter Zeichenkettenvergleich als Wahrscheinlichkeit
; von Wert = 0 (totaler Ungleichheit) bis 1 (Gleichheit)Func min3($a, $b, $c)
[/autoit] [autoit][/autoit] [autoit]
Local $dummy
$dummy = $a
If $b < $dummy Then $dummy = $b
If $c < $dummy Then $dummy = $c
Return $dummy
EndFunc ;==>min3Func LevenshteinDistance($s, $t)
[/autoit] [autoit][/autoit] [autoit]
Local $n, $m
$n = StringLen($s)
$m = StringLen($t)
If $s = $t Then Return 0
If $s = "" Then Return $m
If $t = "" Then Return $n
Local $d[$n + 1][$m + 1], $i, $j, $cost
For $i = 0 To $n
$d[$i][0] = $i
Next
For $j = 0 To $m
$d[0][$j] = $j
Next
For $i = 1 To $n
For $j = 1 To $m
If StringMid($s, $i, 1) = StringMid($t, $j, 1) Then
$cost = 0
Else
$cost = 1
EndIf
$d[$i][$j] = min3($d[$i - 1][$j] + 1, $d[$i][$j - 1] + 1, $d[$i - 1][$j - 1] + $cost)
Next
Next
Return $d[$n][$m]
EndFunc ;==>LevenshteinDistanceFunc CompTstr($s, $t)
[/autoit]
Local $n, $m
$n = StringLen($s)
$m = StringLen($t)
If $n < $m Then $n = $m
Return ($n - LevenshteinDistance($s, $t)) / $n
EndFunc ;==>CompTstr
Das Problem ist bloß, dass diese Funktion zu lange dafür braucht. In einem Test mit ca. 9000 MP3s muss ich jeden Titel mit den anderen 9000 vergleichen. Das ergibt zwei ineinander verschachtelte Schleifen, bei der ein Durchlauf der äußeren Schleife ca. 15 Minuten dauert. 9000 mal 15 Minuten ist mir ehrlich gesagt zu lang, um darauf zu warten. Dann kann ich das gleich von Hand machen.
Gibt es nicht irgendeine andere Möglichkeit die Strings nach Ähnlichkeit zu bewerten?
-
Meinst Du so:
Spoiler anzeigen
[autoit]
[/autoit]
$sPath = @ScriptDir & '\test.xml' ; Pfad ggf. anpassen
$sFile = FileRead($sPath)
$aData = StringRegExp($sFile, '(?s)<file>.*?<filename value="(.+?)".*?<modification value="(.+?)".*?</file>', 3)
$sDate = '0000-00-00'
$iIndex = 0
For $i = 0 To UBound($aData) - 1 Step 2
If StringLeft($aData[$i + 1], 10) > $sDate Then
$sDate = StringLeft($aData[$i + 1], 10)
$iIndex = $i
EndIf
Next
MsgBox(0, 'Datei mit neuestem Datum:', $aData[$iIndex])
Hab zum testen die XML-Datei mit den tgz-Einträgen genommen. -
Das hast Du jetzt aber verschwiegen, dass bei einer ungeraden Anzahl an Zahlen noch eine Null hinzukommt.
Kleine Änderung bei dem Script von Andy:Spoiler anzeigen
[autoit]
[/autoit] [autoit][/autoit] [autoit]
Global $zahl = '10012', $iLen = StringLen($zahl)
If Int($iLen/2) <> $iLen/2 Then $zahl &= '0'
MsgBox(0, "", "Die Quersumme von " & $zahl & " ist " & _quersumme($zahl))Func _quersumme($ziffern)
[/autoit]
Local $zahl = String($ziffern) ;einen String machen
Local $quer = 0
For $i = 1 To StringLen($zahl) ;jede einzelne Ziffer...
$quer += Number(StringMid($zahl, $i, 1)) ;...zusammenzählen
Next
$zahl = String($quer) ;aus der quersumme wieder einen string machen
If StringLen($zahl) = 1 Then Return $zahl ;wenn nur eine Ziffer übrig bleibt, raus
$zahl = _quersumme($zahl) ;die quersumme hat mehr wie eine ziffer, dann rekursiov weiter
Return $zahl ;ergebnis aus der rekursion zurückgeben
EndFunc ;==>_quersumme -
Ach, hattest auch einen Thread aufgemacht...
Habe Dir die Lösung zwar bereits als PN geschickt, aber vielleicht braucht es ja noch jemand (oder kennt eine bessere Lösung):Spoiler anzeigen
[autoit]
[/autoit] [autoit][/autoit] [autoit]
$sNumber = '8705'
$aNumber = StringRegExp($sNumber, '.{2}', 3)
$sSum = ''
For $i = 0 To UBound($aNumber) - 1
$sSum &= _AddNumbers($aNumber[$i])
Next
If StringLen($sSum) = 2 Then $sSum = _AddNumbers($sSum)
MsgBox(0, 'Ergebnis', $sSum)Func _AddNumbers($sNumber)
[/autoit]
$iRes = StringLeft($sNumber, 1) + StringRight($sNumber, 1)
If StringLen($iRes) = 2 Then $iRes = _AddNumbers($iRes)
Return $iRes
EndFunc -
Um mal zu zeigen, wie schnell ein Dictionary.Objekt in dem Fall wäre:
Spoiler anzeigen
[autoit]
[/autoit] [autoit][/autoit] [autoit]
Local $ar3D[500][20][5]
Global $oDictionary = ObjCreate('Scripting.Dictionary')$string = ""
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
For $x = 0 To UBound($ar3D, 1) - 1
For $y = 0 To UBound($ar3D, 2) - 1
For $z = 0 To UBound($ar3D, 3) - 1
$ar3D[$x][$y][$z] = Hex(Random(1000000)) & Hex(Random(1000000)) & Hex(Random(1000000)) & Hex(Random(1000000))
Next
Next
$string &= StringFormat("[%03s]", $x) & $ar3D[$x][0][0]
$oDictionary.Add($ar3D[$x][0][0], $x)
;MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$string' & @lf & @lf & 'Return:' & @lf & $string) ;### Debug MSGBOX
Next$t = TimerInit()
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
$index = __ArraySearch($ar3D, $ar3D[495][0][0])
$arraysearchtime = TimerDiff($t)
ConsoleWrite($index & @CR)$t = TimerInit()
[/autoit] [autoit][/autoit] [autoit]
$index = __stringArraySearch($string, $ar3D[495][0][0])
$stringarraysearchtime = TimerDiff($t)
ConsoleWrite($index & @CR)$t = TimerInit()
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
$index = $oDictionary.Item($ar3D[495][0][0])
$dictionarysearchtime = TimerDiff($t)
ConsoleWrite($index & @CR)MsgBox(0, "Index = " & $index, _
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
StringFormat("__ArraySearch()" & @TAB & @TAB & "%.2f%", $arraysearchtime) & " Millisekunden" & @CRLF & _
StringFormat("__stringArraySearch()" & @TAB & "%.2f%", $stringarraysearchtime) & " Millisekunden" & @CRLF & _
StringFormat("__DictionarySearch()" & @TAB & "%.2f%", $dictionarysearchtime) & " Millisekunden")Func __stringArraySearch($string, $search)
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
$pos = StringInStr($string, $search) - 4
Return Number(StringMid($string, $pos, 3))
EndFunc ;==>__stringArraySearchFunc __ArraySearch(ByRef $array, $search)
[/autoit]
For $i = 0 To UBound($array) - 1
;consolewrite($array[$i][0][0]&@tab&$i&@crlf)
If $array[$i][0][0] = $search Then
Return $i
EndIf
Next
Return -1
EndFunc ;==>__ArraySearch -
Eine andere Überlegung wäre, zusätzlich mit diesen "Such"-Daten ein Scripting.Dictionary-Objekt anzulegen und als Key die Array-Position zu speichern. Mit dem Scripting.Dictionary-Objekt wäre die Suche schneller.