Jak sprawdzić, czy ciąg znaków zaczyna się od liczby w Pythonie?

91

Mam ciąg zaczynający się od liczby (od 0-9) Wiem, że mogę "lub" 10 przypadków testowych z użyciem funkcji startwith (), ale prawdopodobnie istnieje lepsze rozwiązanie

więc zamiast pisać

if (string.startswith('0') || string.startswith('2') ||
    string.startswith('3') || string.startswith('4') ||
    string.startswith('5') || string.startswith('6') ||
    string.startswith('7') || string.startswith('8') ||
    string.startswith('9')):
    #do something

Czy istnieje sprytniejszy / wydajniejszy sposób?

Iluzjonista
źródło
Jeśli zostanie zadane pytanie: „Czy to jest zbyt powtarzalne?”, Są szanse - w języku wysokiego poziomu - odpowiedź brzmi „Dlaczego tak, na pewno jest”. Być leniwym!
42
Przegapiłeś string.startswith('1').
MAK,
2
@Illusionist Jak napisano, Twoje pytanie oznacza, że ​​chcesz wykryć ciągi zaczynające się tylko od JEDNEJ cyfry. Jeśli tak, to jedyną właściwą odpowiedź spośród następujących te nie są te wykorzystujące s[0]albo s[:1]ale rozwiązanie Jana Machin: if s.startswith(tuple('0123456789')). Co więcej, to rozwiązanie generuje błąd, gdy zdarza się, że s jest sekwencją taką jak krotka lub lista, co daje taki sam wynik, jak gdyby był łańcuchem. - Innym rozwiązaniem jest wyrażenie regularne, którego wzorzec to „\ d (? = \ D)”, ale użycie wyrażenia regularnego jest tutaj zbędne.
eyquem,
3
Po prostu pedantyczny: stringto moduł w bibliotece standardowej i prawdopodobnie nie powinien być używany jako nazwa zmiennej. docs.python.org/2/library/string.html
GAK

Odpowiedzi:

170

stringBiblioteka Pythona ma isdigit()metodę:

string[0].isdigit()
plaes
źródło
5
string Moduł Python2 nie ma metod i isdigitjest metodą obiektów stri unicode.
John Machin,
3
@plaes: -1 z powodu powyższego PLUS powoduje awarię, jeśli s == ""
John Machin,
3
Spójrz na moją odpowiedź, która nie przerywa pustego ciągu:string[:1].isdigit()
PascalVKooten
24
>>> string = '1abc'
>>> string[0].isdigit()
True
jcomeau_ictx
źródło
Nie jestem facetem od Pythona, więc może pomożesz mi w tej sprawie: czy ta funkcja zbombarduje "", gdzie nie ma string[0]?
corsiKa
tak, na pewno będzie. możesz użyć (string lub 'x') [0] .isdigit (), aby naprawić to dla '' lub None
jcomeau_ictx
30
Możesz spróbować string[:1].isdigit(), co szczęśliwie zakończy pracę z pustym ciągiem.
Simon Callan,
2
ponieważ to nie jest moja odpowiedź; mój jest jeszcze lepszy w przypadku, gdy programista chce, aby wyjątek został wyrzucony na pusty łańcuch.
jcomeau_ictx
1
@jcomeau_ictx dokładnie tak. nigdy nie programuj obronnie. Jeśli łańcuch jest pusty nieoczekiwanie, że powinien error out i nie powinny być automatycznie przetwarzane tak. Niektóre szkoły myślenia mówią, że należy z wdziękiem obsługiwać i wychwytywać wyjątki, które nie są krytyczne, jako ostrzeżenie i podtrzymywać program. W większości przypadków nie jestem z tego nastawienia. Specyfika funkcji i kodu, który piszesz, pomaga złagodzić skrajne przypadki, w których musiałbyś częściej kodować defensywnie.
jamescampbell
10

czasami możesz użyć wyrażenia regularnego

>>> import re
>>> re.search('^\s*[0-9]',"0abc")
<_sre.SRE_Match object at 0xb7722fa8>
kurumi
źródło
przesada! Po co używać ponownego, skoro można to zrobić w bultinach
Jakob Bowyer,
1
@JakobBowyer Przynajmniej dobrze o tym wiedzieć! Mimo że w tym przypadku tak, wyrażenia regularne SĄ przesadą, jeśli niektóre wbudowane mogą zrobić to samo.
jeromej
8

Twój kod nie zadziała; potrzebujesz orzamiast ||.

Próbować

'0' <= strg[:1] <= '9'

lub

strg[:1] in '0123456789'

a jeśli naprawdę szaleją startswith,

strg.startswith(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'))
John Machin
źródło
Głosowałbym za tobą, gdyby istniało tylko rozwiązanie z literami zaczynającymi się od (krotką) . Ale rozwiązania z strg[:1]mają dwie niedogodności: nie powodują błędu, jeśli s może być listą ciągów, i dają Prawdę, jeśli łańcuch zaczyna się od KILKU cyfr.
eyquem
@eyquem dają Prawdę, jeśli ciąg zaczyna się od KILKU cyfr. Więc? Inne odpowiedzi tego nie sprawdzają, ponieważ nie było wymogiem, aby sprawdzał, czy inne znaki nie są numeryczne.
Rob Grant
I jestem szalona startswithi nie wdrożyć go w ten sposób w moim kodzie. Dziękuję Ci.
jamescampbell
Jeszcze jeden start z możliwością ...startswith(tuple(str(i) for i in range(10)))
Jérôme
4

Ten fragment kodu:

for s in ("fukushima", "123 is a number", ""):
    print s.ljust(20),  s[0].isdigit() if s else False

wypisuje następujące informacje:

fukushima            False
123 is a number      True
                     False
eyquem
źródło
4
To jest brzydkie. Użyj s[:1].isdigit()lubs and s[0].isdigit()
John Machin
1
@John Machin Co masz na myśli mówiąc „brzydki”? Nie czytelne ? Nie uważam, aby twoje propozycje tutaj powyżej były bardziej czytelne. s and s[0].isdigit()jest moim zdaniem jeszcze mniej czytelny. Osobiście jak konstruktem ... jeśli ... else ... Biorąc pod uwagę Twoje uwagi, chciałbym po prostu poprawić go tak:s[0].isdigit() if s!="" else False
eyquem
3

Zaskakujące, że po tak długim czasie nadal brakuje najlepszej odpowiedzi.

Wadą innych odpowiedzi jest użycie [0]do wybrania pierwszego znaku, ale jak wspomniano, powoduje to przerwanie pustego ciągu.

Skorzystanie z poniższego omija ten problem i, moim zdaniem, daje najładniejszą i najbardziej czytelną składnię z dostępnych opcji. Również nie importuje / nie zawraca sobie głowy wyrażeniem regularnym):

>>> string = '1abc'
>>> string[:1].isdigit()
True

>>> string = ''
>>> string[:1].isdigit()
False
PascalVKooten
źródło
2

Możesz również użyć try...except:

try:
    int(string[0])
    # do your stuff
except:
    pass # or do your stuff
Jedna twarz
źródło
1

Oto moje „odpowiedzi” (staram się być tutaj wyjątkowy, nie polecam żadnego w tym konkretnym przypadku :-)

Za pomocą ord () ispecjalny a <= b <= cformularz:

//starts_with_digit = ord('0') <= ord(mystring[0]) <= ord('9')
//I was thinking too much in C. Strings are perfectly comparable.
starts_with_digit = '0' <= mystring[0] <= '9'

(To a <= b <= c, jak a < b < cjest specjalnym konstrukt Python i jest to rodzaj schludne porównanie 1 < 2 < 3(prawda) i 1 < 3 < 2(fałsz) i (1 < 3) < 2(prawda), to nie jest to, jak to działa w większości innych języków.).

Używając wyrażenia regularnego :

import re
//starts_with_digit = re.match(r"^\d", mystring) is not None
//re.match is already anchored
starts_with_digit = re.match(r"\d", mystring) is not None

źródło
1
(1) Zgub ord()(2) Zgub ^w wyrażeniu regularnym.
John Machin,
0

Możesz użyć wyrażeń regularnych .

Możesz wykryć cyfry za pomocą:

if(re.search([0-9], yourstring[:1])):
#do something

Par [0-9] pasuje do dowolnej cyfry, a twój łańcuch [: 1] pasuje do pierwszego znaku twojego ciągu

Tovi7
źródło
-2

Użyj wyrażeń regularnych , jeśli masz zamiar w jakiś sposób rozszerzyć funkcjonalność metody.

Ilya Smagin
źródło
-5

Spróbuj tego:

if string[0] in range(10):
bradley.ayers
źródło
To w ogóle nie działa. range(10)tworzy listę liczb całkowitych, podczas gdy string[0]jest to ciąg o długości 1.
Petri Lehtinen
1
To nie działa; typy się nie zgadzają. Ale: if string[0] in map(str,range(10))działa
phynfo