Zahl vom Anfang eines Strings auslesen

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.
Antworten
Lasse
User
Beiträge: 112
Registriert: Donnerstag 3. Februar 2011, 18:25

Hallo,
ich möchte eine Zahl vom Anfang eines Strings auslesen. Der String sieht zum Beispiel so aus aus "12Akajnajfaj34fjakfjka5kjkj". Jetzt möchte ich nur noch die 12 haben. Wie geht das am einfachsten?

Danke :)
BlackJack

@Lasse: Dafür könnte man das `re`-Modul benutzen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mit einem regulären Ausdruck:

Code: Alles auswählen

In [5]: import re

In [6]: res = re.search(r"\d+", "12Akajnajfaj34fjakfjka5kjkj")

In [7]: res.group()
Out[7]: '12'
Wenn Du die Suche öfter durchführst, dann würde ich den Ausdruck noch kompilieren mit `re.compile`.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
problembär

Ein regulärer Ausdruck mit dem 're'-Modul wäre wohl auch meine erste Wahl.

Andererseits vermeidet Python soweit wie möglich reguläre Ausdrücke und verwendet stattdessen besser lesbare Funktionen wie ".startswith()" oder ".replace()".
Ich könnte mir also auch sowas vorstellen:

Code: Alles auswählen

a = "12Akajnajfaj34fjakfjka5kjkj"
b = ""
while len(a) > 0 and a[0].isdigit():
    b += a[0]
    a = a[1:]
print b
Muß aber nicht. 're' ist auch ok (und wahrscheinlich auch schneller), wenn man damit umgehen kann (was z.B. für Anfänger wohl nicht so ganz leicht ist).
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Anstelle mit Indices und `while` geht es auch wie folgt ganz schön:

Code: Alles auswählen

In [36]: a = "12Akajnajfaj34fjakfjka5kjkj"

In [37]: b = ''

In [38]: for c in a:
   ....:     if c.isdigit():
   ....:         b += c
   ....:     else:
   ....:         break
   ....:         

In [39]: b
Out[39]: '12'
Ansonsten ginge auch folgendes. Allerdings bin ich mir nicht sicher, ob das Verhalten gewollt ist:

Code: Alles auswählen

In [33]: def break_():
   ....:     raise StopIteration
   ....: 

In [34]: a = "12Akajnajfaj34fjakfjka5kjkj"

In [35]: ''.join(c if c.isdigit() else break_() for c in a)
Out[35]: '12'
Grüße
Gerrit
problembär

gkuhl hat geschrieben:

Code: Alles auswählen

In [36]: a = "12Akajnajfaj34fjakfjka5kjkj"

In [37]: b = ''

In [38]: for c in a:
   ....:     if c.isdigit():
   ....:         b += c
   ....:     else:
   ....:         break
Stimmt, das gefällt mir auch viel besser.
Lasse
User
Beiträge: 112
Registriert: Donnerstag 3. Februar 2011, 18:25

Danke an alle!
Ich verwende erst einmal die Lösung von gkuhl, werde aber auch noch die re-Variante ausprobieren.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

problembär hat geschrieben: Andererseits vermeidet Python soweit wie möglich reguläre Ausdrücke und verwendet stattdessen besser lesbare Funktionen wie ".startswith()" oder ".replace()".
Was heißt "Python" vermeidet etwas? Der Interpreter? Die Sprache an sich? Belege?
problembär hat geschrieben: Ich könnte mir also auch sowas vorstellen:

Code: Alles auswählen

a = "12Akajnajfaj34fjakfjka5kjkj"
b = ""
while len(a) > 0 and a[0].isdigit():
    b += a[0]
    a = a[1:]
print b
Oha... eine schlechtere Lösung ist kaum vorstellbar! Das Laufzeitverhalten davon ist furchtbar, vom Speicherverbrauch mal abgesehen. Ist Dir klar, was da alles passiert im einzelnen?

Die Variante von gkuhl ist da schon besser; sinnvoller Weise vergisst man mal schnell die Stringkonkatenation mittels "+" und nutzt eine Liste und anschließend `join`:

Code: Alles auswählen

In [46]: res = []

In [47]: for c in data:
   ....:     if c.isdigit():
   ....:         res.append(c)
   ....:     else:
   ....:         break
   ....:         
   ....:         

In [48]: res
Out[48]: ['1', '2']

In [49]: "".join(res)
Out[49]: '12'
Also wenn schon ohne `re`-Modul, dann eben mit den `itertools`:

Code: Alles auswählen

In [44]: from itertools import takewhile

In [45]: "".join(takewhile(lambda c: c.isdigit(), data))
Out[45]: '12'
Ich denke problembär würde diese Lösung am liebsten als Teufelswerk verbrennen :twisted:

@Lasse: Mal ganz im Ernst: Die Lösung mit dem `re`-Modul ist am einfachsten - das sollte auch ein Anfänger sehen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@gkuhl: Eine Iteratorlösung ginge auch mit `operator.methodcaller()` (oder einer ``lambda``-Funktion) und `itertools.takewhile()`:

Code: Alles auswählen

In [101]: ''.join(takewhile(methodcaller('isdigit'), a))
Out[101]: '12'
Edit: Mist, zu langsam. :-)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben: Edit: Mist, zu langsam. :-)
Yihaaa! Zum ersten Mal BlackJack "geschlagen" :P
...
Wobei ich `methodcaller` noch nicht kannte... :( ist das eigentlich `lambda` zu bevorzugen? (Wieso eigentlich `method` und nicht `function`?)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Hyperion hat geschrieben:Wieso eigentlich `method` und nicht `function`?
Vielleicht, weil es Methoden und keine Funktionen aufruft? ;)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

nomnom hat geschrieben:
Hyperion hat geschrieben:Wieso eigentlich `method` und nicht `function`?
Vielleicht, weil es Methoden und keine Funktionen aufruft? ;)
:oops: Ich sollte zu Bett gehen... danke!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

BlackJack hat geschrieben:

Code: Alles auswählen

In [101]: ''.join(takewhile(methodcaller('isdigit'), a))
Ist das besser als

Code: Alles auswählen

''.join(takewhile(str.isdigit, a))
?
lunar

@bords0: Deine Variante kommt nicht mit "unicode"-Objekten klar:

Code: Alles auswählen

 In [14]: a = u'12'

In [15]: ''.join(takewhile(methodcaller('isdigit'), a))
Out[15]: u'12'

In [16]: ''.join(takewhile(str.isdigit, a))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/lunar/<ipython-input-16-112f36c1e07f> in <module>()
----> 1 ''.join(takewhile(str.isdigit, a))

TypeError: descriptor 'isdigit' requires a 'str' object but received a 'unicode'
Antworten