Deutsches AutoHotkey Homepage AutoHotkey Community
Wir helfen uns gegenseitig aus der Patsche
 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   RegistrierenRegistrieren 
 ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

[Funktion] DelSpaces(str)
Gehe zu Seite 1, 2, 3  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    AutoHotkey Community Foren-Übersicht -> Skripte & Funktionen
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
haichen



Anmeldedatum: 10.06.2007
Beiträge: 75

BeitragVerfasst am: Do Feb 28, 2008 2:00 am    Titel: [Funktion] DelSpaces(str) Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
DerRaphael



Anmeldedatum: 09.01.2008
Beiträge: 576
Wohnort: Zuhause

BeitragVerfasst am: Do Feb 28, 2008 11:15 am    Titel: Antworten mit Zitat

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 Smile
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
haichen



Anmeldedatum: 10.06.2007
Beiträge: 75

BeitragVerfasst am: Do Feb 28, 2008 12:16 pm    Titel: Antworten mit Zitat

Cool 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
Benutzer-Profile anzeigen Private Nachricht senden
DerRaphael



Anmeldedatum: 09.01.2008
Beiträge: 576
Wohnort: Zuhause

BeitragVerfasst am: Do Feb 28, 2008 12:23 pm    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
haichen



Anmeldedatum: 10.06.2007
Beiträge: 75

BeitragVerfasst am: Do Feb 28, 2008 1:32 pm    Titel: Antworten mit Zitat

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" ! Wink
Trotzdem sehr beeindruckend.
Very Happy
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DerRaphael



Anmeldedatum: 09.01.2008
Beiträge: 576
Wohnort: Zuhause

BeitragVerfasst am: Do Feb 28, 2008 3:40 pm    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
BoBo¨
Gast





BeitragVerfasst am: Do Feb 28, 2008 5:32 pm    Titel: Antworten mit Zitat

Und da wir hier in Deutschelande sind, hier noch die abschließende Legitimation der finalen Version von DeleteSpace(str)



Cool
Nach oben
DerRaphael



Anmeldedatum: 09.01.2008
Beiträge: 576
Wohnort: Zuhause

BeitragVerfasst am: Do Feb 28, 2008 5:34 pm    Titel: Antworten mit Zitat

rofl
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
haichen



Anmeldedatum: 10.06.2007
Beiträge: 75

BeitragVerfasst am: Do Feb 28, 2008 6:15 pm    Titel: Antworten mit Zitat

Glückwunsch! Very Happy

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
Benutzer-Profile anzeigen Private Nachricht senden
Chucky



Anmeldedatum: 07.01.2006
Beiträge: 576
Wohnort: Powerland

BeitragVerfasst am: Do Feb 28, 2008 9:23 pm    Titel: Antworten mit Zitat

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 Very Happy
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
fredchf



Anmeldedatum: 18.09.2006
Beiträge: 605
Wohnort: Deutschland

BeitragVerfasst am: Do Feb 28, 2008 10:30 pm    Titel: Antworten mit Zitat

hallo und danke erstmal für eure interessanten posts! Laughing

@Chucky:
ich habe leider mit "Wortgrenze" keine guten erfahrungen gemacht,weil etwa umlaute oder "ß" nicht als wortgrenze behandelt werden. Crying or Very sad
ein umlaut als erster buchstabe eines wortes in Str würde leider auch deine regex scheitern lassen. Wink
_________________
Mit freundlichen Grüßen
fredchf
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Chucky



Anmeldedatum: 07.01.2006
Beiträge: 576
Wohnort: Powerland

BeitragVerfasst am: Do Feb 28, 2008 10:47 pm    Titel: Antworten mit Zitat

fredchf hat Folgendes geschrieben:
ein umlaut als erster buchstabe eines wortes in Str würde leider auch deine regex scheitern lassen. Wink
(um Ausreden nie verlegen) Ja nee is klaaar, war ja auch 'n englischer Text Laughing !
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DerRaphael



Anmeldedatum: 09.01.2008
Beiträge: 576
Wohnort: Zuhause

BeitragVerfasst am: Do Feb 28, 2008 10:56 pm    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Chucky



Anmeldedatum: 07.01.2006
Beiträge: 576
Wohnort: Powerland

BeitragVerfasst am: Fr Feb 29, 2008 12:16 am    Titel: Antworten mit Zitat

Yep - wenn gefordert ist, daß keine Tabs stehenbleiben dürfen. Überflüssige Tabs (= alles über 1 Tab) werden aber schon entfernt.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DerRaphael



Anmeldedatum: 09.01.2008
Beiträge: 576
Wohnort: Zuhause

BeitragVerfasst am: Fr Feb 29, 2008 12:40 am    Titel: Antworten mit Zitat

im ersten posting von haichen wurden jegliche tabs durch spaces ersetzt.
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    AutoHotkey Community Foren-Übersicht -> Skripte & Funktionen Alle Zeiten sind GMT
Gehe zu Seite 1, 2, 3  Weiter
Seite 1 von 3

 
Gehe zu:  
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