Seite 1 von 1

Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 17:26
von Lasse
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 :)

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 17:32
von BlackJack
@Lasse: Dafür könnte man das `re`-Modul benutzen.

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 17:33
von Hyperion
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`.

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 19:25
von 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).

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 19:45
von gkuhl
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

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 20:03
von 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.

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 21:44
von Lasse
Danke an alle!
Ich verwende erst einmal die Lösung von gkuhl, werde aber auch noch die re-Variante ausprobieren.

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 22:20
von Hyperion
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.

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 22:22
von 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. :-)

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 22:29
von Hyperion
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`?)

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 22:38
von nomnom
Hyperion hat geschrieben:Wieso eigentlich `method` und nicht `function`?
Vielleicht, weil es Methoden und keine Funktionen aufruft? ;)

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 22:39
von Hyperion
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!

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 23:29
von bords0
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))
?

Re: Zahl vom Anfang eines Strings auslesen

Verfasst: Samstag 17. Dezember 2011, 23:48
von 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'