re.sub

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

re.sub

Beitragvon HarryH » Mittwoch 21. Januar 2004, 14:05

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
Gruß, Harry
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Re: re.sub

Beitragvon Voges » Mittwoch 21. Januar 2004, 14:39

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
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Mittwoch 21. Januar 2004, 15:10

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
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

re:

Beitragvon HarryH » Mittwoch 21. Januar 2004, 15:26

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
Gruß, Harry
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Mittwoch 21. Januar 2004, 17:03

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
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Beitragvon Voges » Mittwoch 21. Januar 2004, 17:31

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
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Mittwoch 21. Januar 2004, 17:53

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
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Beitragvon Voges » Mittwoch 21. Januar 2004, 18:28

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.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder