Seite 1 von 1

re.sub

Verfasst: Mittwoch 21. Januar 2004, 14:05
von HarryH
Hallo,

Geht das auch schneller oder besser?

Code: Alles auswählen

import re
s="C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
for i,j in zip([" ",r"\\","\+"],["_",r"\\\\","-"]):s=re.sub(i,j,s)
print s
Würde mich über Anregungen freuen. Danke

Re: re.sub

Verfasst: Mittwoch 21. Januar 2004, 14:39
von Voges
Hallo!
HarryH hat geschrieben:

Code: Alles auswählen

s="C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
Dass das für Python eine korrektes String-Literal ist, finde ich eigenwillig. Bei Compilern/Interpretern anderer Sprachen wird man zumindest mit einem Warning darauf aufmerksam gemacht, dass es die Escape-Sequenzen \D, \A und \H nicht gibt.

Mein Vorschlag für die Ersetzung:
for t in ((" ","_"),("","\\"),("+","-")): s = s.replace(*t)

Jan

Verfasst: Mittwoch 21. Januar 2004, 15:10
von Dookie
Hallo HarryH,

Mein Vorschlag wäre

Code: Alles auswählen

s="C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
replacedict = {" ":"_", "\\":"\\\\", "+":"-"}
s = "".join(map(lambda x: rd.get(x,x), s))
Bei Python2.3 kannst Du die letzte Zeile auch durch

Code: Alles auswählen

s = "".join([rd.get(x,x) for x in s])
ersetzen.
Welche version schnelle ist müsste man testen.


Gruß

Dookie

re:

Verfasst: Mittwoch 21. Januar 2004, 15:26
von HarryH
Hallo Dookie, Jan

Ich habe mal ausprobiert was am schnellsten geht.

Code: Alles auswählen

import re
from time import * 

zeit1=clock()
s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
for i,j in zip([" ",r"\\","\+"],["_",r"\\\\","-"]):s=re.sub(i,j,s)
zeit2=clock()
erg=zeit2-zeit1
print "1.Beispiel: Laufzeit = %.3f Sekunden" % erg
    
zeit1=clock()
s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
for t in ((" ","_"),("\\","\\\\"),("+","-")): s = s.replace(*t)
zeit2=clock()
erg=zeit2-zeit1
print "2.Beispiel: Laufzeit = %.3f Sekunden" % erg

zeit1=clock()
s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz" 
rd = {" ":"_", "\\":"\\\\", "+":"-"} 
s = "".join(map(lambda x: rd.get(x,x), s))
zeit2=clock()
erg=zeit2-zeit1
print "3.Beispiel: Laufzeit = %.3f Sekunden" % erg
Ausgabe:
1.Beispiel: Laufzeit = 0.920 Sekunden
2.Beispiel: Laufzeit = 0.324 Sekunden
3.Beispiel: Laufzeit = 5.833 Sekunden

Somit ist die Lösung von Jan die schnellste.

Dookie, ich habe die Variable "replacedict" in "rd" umgeschrieben, da du sie in deinem Beispiel später auch als "rd" verwendet hast. :D

Verfasst: Mittwoch 21. Januar 2004, 17:03
von Dookie
das kommt davon, wenn man im letzten momoent noch was ändert ;)
folgende Methode dürfte wohl die schnellste Variante sein:

Code: Alles auswählen

s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
s = s.replace(" ", "_")
s = s.replace("\\", "\\\\")
s = s.replace("+", "-")
die ist interessanterweise schneller als folgende:

Code: Alles auswählen

s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
s = s.replace(" ", "_").replace("\\", "\\\\").replace("+", "-")
Gruß

Dookie

Verfasst: Mittwoch 21. Januar 2004, 17:31
von Voges
Hallo!
Dookie hat geschrieben:folgende Methode dürfte wohl die schnellste Variante sein:
Kann ich nicht bestätigen.

Code: Alles auswählen

from time import *
for _ in range(10):
    zeit1=clock()
    s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
    s = s.replace(" ", "_")
    s = s.replace("\", "\\\")
    s = s.replace("+", "-")
    zeit2=clock()
    erg=zeit2-zeit1
    laufzeit = "%.3f / " % erg
    
    zeit1=clock()
    s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
    for t in ((" ","_"),("\","\\\"),("+","-")): s = s.replace(*t)
    zeit2=clock()
    erg=zeit2-zeit1
    laufzeit += "%.3f / " % erg
    
    zeit1=clock()
    s=100000*"C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"
    s = s.replace(" ", "_").replace("\", "\\\").replace("+", "-")
    zeit2=clock()
    erg=zeit2-zeit1
    laufzeit += "%.3f" % erg
    print laufzeit
Ausgabe:
0.295 / 0.303 / 0.301
0.302 / 0.299 / 0.301
0.305 / 0.300 / 0.298
0.304 / 0.301 / 0.301
0.305 / 0.298 / 0.300
0.307 / 0.299 / 0.297
0.304 / 0.298 / 0.301
0.303 / 0.299 / 0.301
0.301 / 0.299 / 0.299
0.303 / 0.303 / 0.298

Naja, tolle Unterschiede sind das nicht. Eher zufällig. Tatsächlich scheint es (auf meinem Rechner) so zu sein, dass die erste Methode in der For-Schleife die langsamste ist, unabhängig davon, welche von den dreien die erste ist.
Jan

Verfasst: Mittwoch 21. Januar 2004, 17:53
von Dookie
Ich hab jetzt mal das Beispiel so verändert, daß nicht ein megalanger String sonder 100000 "normallange" Strings bearbeitet werden. So werden die Unterschiede noch deutlicher.

Code: Alles auswählen

import re
from time import *

sl=100000*["C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"]
zeit1=clock()
for s in sl:
    for i,j in zip([" ",r"\\","\+"],["_",r"\\\\","-"]):s=re.sub(i,j,s)
zeit2=clock()
erg=zeit2-zeit1
print "1.Beispiel: Laufzeit = %.3f Sekunden" % erg
   
sl=100000*["C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"]
zeit1=clock()
for s in sl:
    for t in ((" ","_"),("\\","\\\\"),("+","-")): s = s.replace(*t)
zeit2=clock()
erg=zeit2-zeit1
print "2.Beispiel: Laufzeit = %.3f Sekunden" % erg

sl=100000*["C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"]
zeit1=clock()
for s in sl:
    s = s.replace(" ", "_").replace("\\", "\\\\").replace("+", "-")
zeit2=clock()
erg=zeit2-zeit1
print "3.Beispiel: Laufzeit = %.3f Sekunden" % erg

sl=100000*["C:\Dokumente und Einstellungen\All Users\Dokumente\Hinz+Kunz"]
zeit1=clock()
for s in sl:
    s = s.replace(" ", "_")
    s = s.replace("\\", "\\\\")
    s = s.replace("+", "-")
zeit2=clock()
erg=zeit2-zeit1
print "4.Beispiel: Laufzeit = %.3f Sekunden" % erg
Ich hab mal drei Durchläufe rechnen lassen.

Code: Alles auswählen

fritz@seneca:~/Python/Beispiele$ python replacetest.py
1.Beispiel: Laufzeit = 9.250 Sekunden
2.Beispiel: Laufzeit = 1.510 Sekunden
3.Beispiel: Laufzeit = 1.120 Sekunden
4.Beispiel: Laufzeit = 1.170 Sekunden
fritz@seneca:~/Python/Beispiele$ python replacetest.py
1.Beispiel: Laufzeit = 10.020 Sekunden
2.Beispiel: Laufzeit = 1.570 Sekunden
3.Beispiel: Laufzeit = 1.200 Sekunden
4.Beispiel: Laufzeit = 1.250 Sekunden
fritz@seneca:~/Python/Beispiele$ python replacetest.py
1.Beispiel: Laufzeit = 9.740 Sekunden
2.Beispiel: Laufzeit = 1.590 Sekunden
3.Beispiel: Laufzeit = 1.190 Sekunden
4.Beispiel: Laufzeit = 1.280 Sekunden

Gruß

Dookie

Verfasst: Mittwoch 21. Januar 2004, 18:28
von Voges
Hallo!
Dookie hat geschrieben:Ich hab jetzt mal das Beispiel so verändert, daß nicht ein megalanger String sonder 100000 "normallange" Strings bearbeitet werden. So werden die Unterschiede noch deutlicher.
Das ist natürlich eine ganz andere Aufgabenstellung:
Im ersten Ansatz hast Du 3 replace()-Aufrufe versucht, zu optimieren, was bei einem String von 6 Mio. Zeichen erwartungsgemäß nichts bringt. Dass das jetzt im zweiten Ansatz bei 300000(!) replace()-Aufrufen (bei einem 60-Zeichen-String) ganz anders aussehen muss, ist klar. Also HarryH, nächstes Mal bitte eine klare Aufgabenstellung ;-)

Wichtig fände ich allerdings auch die "Universalität" einer Lösung. Drei fest kodierte replace()-Aufrufe sind weniger flexibel, als ein replace()-Aufruf, dessen Häufigkeit nur von der Länge eines Tuples oder einer Liste abhängt. Und ich sehe gerade gefordert war "schneller und besser" ;-)

Code: Alles auswählen

tpls = ((" ","_"),("\","\\\"),("+","-"))
for s in sl:
    for t in tpls: s = s.replace(*t)
Damit mach' ich noch ein paar Hundertstel gut. Aber an den Windabweisern und dem Heckspoiler muss ich noch basteln.

Jan

Nachtrag: An den Reifen lag's.

Code: Alles auswählen

ttbl = string.maketrans(" +","_-")
for s in sl:
    s = s.translate(ttbl)
    s = s.replace("\", "\\\")
Superschnell und völlig un-universell.