 |
AutoHotkey Community Wir helfen uns gegenseitig aus der Patsche
|
| Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
| Autor |
Nachricht |
haichen
Anmeldedatum: 10.06.2007 Beiträge: 75
|
Verfasst am: Do Feb 28, 2008 2:00 am Titel: [Funktion] DelSpaces(str) |
|
|
Habe ich schon im englischen Forum geschrieben.
Die kleine Funktion entfernt überflüssige Leerzeichen und Tabs. Auch wenn AutoTrim ausgestellt ist.
Wenn keine Tabs im String vorkommen, kann man das Stringreplace weglassen. Oder auch, wenn es egal ist, ob ein Tab oder ein Leerzeichen stehenbleiben.
| Code: | AutoTrim, Off
Str := " The Quick Brown Fox Jumps Brown Over the Lazy Dog "
str := DelSpaces(str)
msgbox, [%str%]
DelSpaces(str){
StringReplace, Str, Str,%a_tab%,%a_space%, All
str :=RegExReplace(Str,"^\s+|\s+(?=\s)|\s$")
return %str%
} |
Ergebnis: [The Quick Brown Fox Jumps Brown Over the Lazy Dog] |
|
| Nach oben |
|
 |
DerRaphael
Anmeldedatum: 09.01.2008 Beiträge: 576 Wohnort: Zuhause
|
Verfasst am: Do Feb 28, 2008 11:15 am Titel: |
|
|
hallo,
| Code: | AutoTrim, Off
Str := " The Quick Brown Fox Jumps Brown Over the Lazy Dog "
msgbox, % "[" DelSpaces(str) "]"
DelSpaces(str,m=0){
return % (!m) ? DelSpaces(RegExReplace(str,"^\s+|\s+$"),1) : RegExReplace(str,"\s+"," ")
}
|
geht auch so  _________________
|
|
| Nach oben |
|
 |
haichen
Anmeldedatum: 10.06.2007 Beiträge: 75
|
Verfasst am: Do Feb 28, 2008 12:16 pm Titel: |
|
|
Cool ,
aber könntest Du das vielleicht mal erklären? Scheint eine Rekursion zu sein? Oder? Ich werde aber leider nicht ganz (und gar nicht) schlau daraus. |
|
| Nach oben |
|
 |
DerRaphael
Anmeldedatum: 09.01.2008 Beiträge: 576 Wohnort: Zuhause
|
Verfasst am: Do Feb 28, 2008 12:23 pm Titel: |
|
|
das ist eine rekursion:
die funktion delspace hat einen parameter extra bekommen (m=0)
beim ersten aufruf wird vorne und hinten getrimmt (whitespaces aller art)
und das so getrimmte regexergebnis ruft sich selbst nochmals auf (ternary m=0) mit dem parameter m=1, um alle (mehrfachen) whitespaces gegen ein einfaches leerzeichen zu tauschen (zweite regex) - das ergebnis wird dann zurückgegeben.
das heißt die funktion ruft sich selbst immer zweimal auf - rekursiv halt.
grüße
derRaphael _________________
|
|
| Nach oben |
|
 |
haichen
Anmeldedatum: 10.06.2007 Beiträge: 75
|
Verfasst am: Do Feb 28, 2008 1:32 pm Titel: |
|
|
Ja danke für die Erläuterung.
Ich hatte zunächst übersehen das mit m=0 und (!m) der Ausdruck beim 1. Aufruf True ist.
Da beide RegReplace() immer nacheinander aufgerufen werden, ist das vom Ergebnis eigentlich dasselbe wie sie hintereinander zu schreiben.
Das ist wahre "Obfuscation" !
Trotzdem sehr beeindruckend.
 |
|
| Nach oben |
|
 |
DerRaphael
Anmeldedatum: 09.01.2008 Beiträge: 576 Wohnort: Zuhause
|
Verfasst am: Do Feb 28, 2008 3:40 pm Titel: |
|
|
weil mir das keine ruhe gelassen hat, habe ich einen kleinen benchmark programmiert, der feststellt, wie lange welche funktion benötigt.
zusätzlich habe ich eine weiter möglichkeit hinzugefügt, die auschließlich mit strreplace und substr arbeitet.
| Code: |
; schneller modus für das skript
SetBatchLines, -1
MsgBox % "Dieser Benchmark testet drei unterschiedliche Methoden,`n"
. "um aus einem Teststring doppelte Vorkommen von Leerzeichen`n"
. "und Tabulatoren zu entfernen."
; freq enthält qpc einheiten per sek
DllCall("QueryPerformanceFrequency","int64*",freq)
DllCall("QueryPerformanceCounter", "Int64 *", start)
log("benchmark start: " a_now)
; DemoText aufbauen
Str1_base := " the quick brown fox jumps over the lazy dog "
Str2_base := " franz jagt im komplett verwahrlosten taxi quer durch Bayern "
log("Basis Strings aufgebaut")
iR := 50 ; innere Rundenanzahl
aR := 10 ; äußere Rundenanzahl
log("Teststart (" aR " Runden zu je " iR " Testaufrufen pro Funktion)`n=================`n")
Loop, %aR%
{
log(A_Index ". Runde")
; str1_base und str2_base mit zufallszeichen bestücken
str := str1 := str2 := ""
Loop, Parse, Str1_base, %A_Space%
str1 .= ZST() A_LoopField
str1c := "(leerzeichen: " anzahl(str1,"\x20") "|tabulatoren: " anzahl(str1,"\x09") ")"
log("String1 entworfen: " str1c)
Loop, Parse, Str2_base, %A_Space%
str2 .= ZST() A_LoopField
str2c := "(leerzeichen: " anzahl(str2,"\x20") "|tabulatoren: " anzahl(str2,"\x09") ")"
log("String2 entworfen: " str2c)
; str basistext aufbauen
Loop, 1000 {
runde = A_Index
loop, 2
str .= str%A_Index% "`n"
}
log("Teststring fertig: " strlen(str) " Zeichen.")
DllCall("QueryPerformanceCounter", "Int64 *", vorher)
loop, %iR%
{
; UDF aufruf
delsp1(str)
}
DllCall("QueryPerformanceCounter", "Int64 *", nachher)
t1 := (nachher - vorher) / freq / iR
erg1 .= t1 "`t"
log("Erster Test (UDF:" iR "x delsp1) absolviert.")
DllCall("QueryPerformanceCounter", "Int64 *", vorher)
loop, %iR%
{
; UDF aufruf
delsp2(str,m=0)
}
DllCall("QueryPerformanceCounter", "Int64 *", nachher)
t2 := (nachher - vorher) / freq / iR
erg2 .= t2 "`t"
log("Zweiter Test (UDF:" iR "x delsp2) absolviert.")
DllCall("QueryPerformanceCounter", "Int64 *", vorher)
loop, %iR%
{
; UDF aufruf
delsp3(str)
}
DllCall("QueryPerformanceCounter", "Int64 *", nachher)
t3 := (nachher - vorher) / freq / iR
erg3 .= t3 "`t"
log("Dritter Test (UDF:" iR "x delsp3) absolviert.")
}
log("`nBerechne Durchscnittswerte.")
Loop, 3 { ; Durchschnittswerte berechnen
summe = 0
Loop, Parse, erg%A_Index%, %A_Tab%
if A_LoopField !=
summe += A_LoopField
ds%A_Index% := summe/aR
}
DllCall("QueryPerformanceCounter", "Int64 *", ende)
msgbox % dauer := (ende-start)/freq
Tooltip
MsgBox,64, % "DelSpace Benchmark: strreplace/regex vs. regex rekursiv vs. strreplace/substr"
, % "Gesamttestdauer: " dauer
. "`n`nMethode Eins (StrReplace, RegExReplace),`tDurchschnittsdauer:"
. ds1 "Sekunden/Aufruf`n" erg1
. "`n`nMethode Zwei (RegExReplace, RegExReplace),`tDurchschnittsdauer:"
. ds2 "`Sekunden/Aufrufn" erg2
. "`n`nMethode Drei (StrReplace, SubStr Kombination),`tDurchschnittsdauer:"
. ds3 "Sekunden/Aufruf`n" erg3
. "Die unter dem allgemeinen Durchschnitt angegebenen Werte`n"
. "sind die ermittelten Durchschnittswerte in Sekunden pro Aufruf der jeweiligen Runde"
return
;************* [ TST User Defined Functions (UDF) Start ] *************
delsp1(str){
StringReplace, Str, Str,%a_tab%,%a_space%, All
str :=RegExReplace(Str,"^\s+|\s+(?=\s)|\s$")
return %str%
}
delsp2(str,m=0)
{
return % (!m) ? delsp2(RegExReplace(str,"^\s+|\s+$"),1) : RegExReplace(str,"\s+"," ")
}
delsp3(str)
{
StringReplace, Str, Str,%a_tab%,%a_space%, All
loop,
if (instr(str," "))
StringReplace, Str, Str,%a_space%%a_space%,%A_space%, All
else
break
if (substr(str,1,1)=" ")
str := substr(str,2)
if (substr(str,0)=" ")
str := substr(str,1,-1)
return %str%
}
;************* [ TST User Defined Functions (UDF) Ende ] *************
;************* [ Benchmark User Defined Functions (UDF) Helperfunktions ] *************
log(newline,keep=5,max=30,x=10,y=10)
{
CoordMode, ToolTip, Screen
global tttxt
tttxt .= newline "`n"
head := body := ""
anz := anzahl(tttxt,"\x0a")
if (anz>max) {
loop,parse,tttxt,`n,`r
{
if (a_index<=keep)
head .= A_LoopField "`n"
if (a_index>(anz+keep-max))
body .= A_LoopField "`n"
}
ntxt := head body
} else {
ntxt := tttxt
}
ToolTip,% regexreplace(ntxt,"(\x0a\x0d?)+$")
,%x%,%y%,1
}
ZST(mixmode=2,min=1,max=5)
{
our := ""
Random, Anz, %min%, %max%
loop, %Anz%
{
if (mixmode=2) {
Random, ChrCode, 0, 1
chr := (ChrCode) ? " " : "`t"
} else {
chr := (mixmode) ? " " : "`t"
}
out .= chr
}
return out
}
anzahl(str,char)
{
blah := regexreplace(str,char," ",anz)
return anz
}
|
wenn der test abgespult wird, werden 10 runden zu je 50 Aufrufen pro funktion ausgeführt. anschließend werden die durchschnittlichen zeiten pro aufruf in sekunden ermittelt und ausgegeben.
die regex in regex funktion ist am langsamsten - was zu erwarten war
dicht gefolgt von der substring regex kombination
eine nur auf strreplace und substr basierende lösung ist die am schnellsten funktionierende!
hiernochmals der TestSieger in Reinform:
| Code: | DeleteSpace(str)
{
StringReplace, Str, Str,%a_tab%,%a_space%, All
loop,
if (instr(str," "))
StringReplace, Str, Str,%a_space%%a_space%,%A_space%, All
else
break
if (substr(str,1,1)=" ")
str := substr(str,2)
if (substr(str,0)=" ")
str := substr(str,1,-1)
return %str%
}
|
grüße
derRaphael _________________
|
|
| Nach oben |
|
 |
BoBo¨ Gast
|
Verfasst am: Do Feb 28, 2008 5:32 pm Titel: |
|
|
Und da wir hier in Deutschelande sind, hier noch die abschließende Legitimation der finalen Version von DeleteSpace(str)
 |
|
| Nach oben |
|
 |
DerRaphael
Anmeldedatum: 09.01.2008 Beiträge: 576 Wohnort: Zuhause
|
Verfasst am: Do Feb 28, 2008 5:34 pm Titel: |
|
|
rofl _________________
|
|
| Nach oben |
|
 |
haichen
Anmeldedatum: 10.06.2007 Beiträge: 75
|
Verfasst am: Do Feb 28, 2008 6:15 pm Titel: |
|
|
Glückwunsch!
Ich glaube der Testsieger kanns noch ein klein wenig besser.
Aber nur wenn AutoTrim = on ist, was aber ja meist der Fall ist.
| Code: | DeleteSpace(str){
StringReplace, Str, Str,%a_tab%,%a_space%, All
loop,
if (instr(str," "))
StringReplace, Str, Str,%a_space%%a_space%,%A_space%, All
else
break
if (A_AutoTrim = "on")
return %str%
if (substr(str,1,1)=" ")
str := substr(str,2)
if (substr(str,0)=" ")
str := substr(str,1,-1)
return %str%
} |
Dieser Beitrag von Laszlo im englische Forum ist auch sehr interressant; aber nicht schneller. |
|
| Nach oben |
|
 |
Chucky
Anmeldedatum: 07.01.2006 Beiträge: 576 Wohnort: Powerland
|
Verfasst am: Do Feb 28, 2008 9:23 pm Titel: |
|
|
Geht noch kürzer:
| Code: | Str := " The Quick Brown Fox Jumps Brown Over the Lazy Dog "
msgbox, % "[" DelSpaces(str) "]"
DelSpaces(str)
{
return RegExReplace(str, "^\s+|\b\s+\B|\s+$", "")
} | Hier wird jedes Leerzeichen + Tab gelöscht, wenn es
- führend ist oder
- links eine Wortgrenze hat, rechts aber nicht oder
- anhängt.
__________________________________________
Created with BBCodeWriter 7.0 - the one and only  |
|
| Nach oben |
|
 |
fredchf
Anmeldedatum: 18.09.2006 Beiträge: 605 Wohnort: Deutschland
|
Verfasst am: Do Feb 28, 2008 10:30 pm Titel: |
|
|
hallo und danke erstmal für eure interessanten posts!
@Chucky:
ich habe leider mit "Wortgrenze" keine guten erfahrungen gemacht,weil etwa umlaute oder "ß" nicht als wortgrenze behandelt werden.
ein umlaut als erster buchstabe eines wortes in Str würde leider auch deine regex scheitern lassen.  _________________ Mit freundlichen Grüßen
fredchf |
|
| Nach oben |
|
 |
Chucky
Anmeldedatum: 07.01.2006 Beiträge: 576 Wohnort: Powerland
|
Verfasst am: Do Feb 28, 2008 10:47 pm Titel: |
|
|
| fredchf hat Folgendes geschrieben: | ein umlaut als erster buchstabe eines wortes in Str würde leider auch deine regex scheitern lassen.  | (um Ausreden nie verlegen) Ja nee is klaaar, war ja auch 'n englischer Text ! |
|
| Nach oben |
|
 |
DerRaphael
Anmeldedatum: 09.01.2008 Beiträge: 576 Wohnort: Zuhause
|
Verfasst am: Do Feb 28, 2008 10:56 pm Titel: |
|
|
chucky des funzt net
| Code: | ---------------------------
spacetrimmer.ahk
---------------------------
-=]The Quick Brown Fox Jumps Brown Over the Lazy Dog[=-
---------------------------
OK
---------------------------
|
bei folgendem test:
| Code: |
AutoTrim, Off
Str := " The Quick Brown Fox Jumps Brown Over the Lazy Dog "
msgbox, % "-=]" D5(str) "[=-"
d5(str)
{
return RegExReplace(str, "^\s+|\b\s+\B|\s+$", "")
} |
vor dog sind zwei tabulatoren
grüße
derRaphael _________________
|
|
| Nach oben |
|
 |
Chucky
Anmeldedatum: 07.01.2006 Beiträge: 576 Wohnort: Powerland
|
Verfasst am: Fr Feb 29, 2008 12:16 am Titel: |
|
|
| Yep - wenn gefordert ist, daß keine Tabs stehenbleiben dürfen. Überflüssige Tabs (= alles über 1 Tab) werden aber schon entfernt. |
|
| Nach oben |
|
 |
DerRaphael
Anmeldedatum: 09.01.2008 Beiträge: 576 Wohnort: Zuhause
|
Verfasst am: Fr Feb 29, 2008 12:40 am Titel: |
|
|
im ersten posting von haichen wurden jegliche tabs durch spaces ersetzt. _________________
|
|
| Nach oben |
|
 |
|
|
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|