Comment savoir si la chaîne commence par un nombre avec Python?

91

J'ai une chaîne qui commence par un nombre (de 0 à 9) Je sais que je peux "ou" 10 cas de test en utilisant beginwith () mais il existe probablement une solution plus soignée

donc au lieu d'écrire

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

Existe-t-il un moyen plus intelligent / plus efficace?

Illusionniste
la source
Si la question est posée: "Est-ce trop répétitif?", Les chances sont - dans un langage de haut niveau - la réponse est "Pourquoi, oui, c'est sûr". Être fainéant!
42
Vous avez manqué string.startswith('1').
MAK
2
@Illusionist Telle qu'elle est écrite, votre question signifie que vous souhaitez détecter les chaînes commençant par UN seul chiffre. Si oui, la seule bonne réponse parmi les suivants, ne sont pas ceux qui utilisent s[0]ou , s[:1]mais la solution de John Machin: if s.startswith(tuple('0123456789')). De plus, cette solution génère une erreur lorsqu'il arrive que s est une séquence comme un tuple ou une liste, ce qui donne le même résultat que s'il s'agissait d'une chaîne. - Une autre solution est une regex dont le motif est '\ d (? = \ D)' mais l'utilisation de regex est ici superflue.
eyquem
3
Être juste pédant: stringest un module de la bibliothèque standard et ne devrait probablement pas être utilisé comme nom de variable. docs.python.org/2/library/string.html
gak

Réponses:

170

La stringbibliothèque de Python a la isdigit()méthode:

string[0].isdigit()
plaes
la source
5
Le string module de Python2 n'a pas de méthodes et isdigitest une méthode d' objets stret unicode
John Machin
3
@plaes: -1 à cause de ce qui précède PLUS il plante si s == ""
John Machin
3
Regardez ma réponse qui ne casse pas pour une chaîne vide:string[:1].isdigit()
PascalVKooten
24
>>> string = '1abc'
>>> string[0].isdigit()
True
jcomeau_ictx
la source
Je ne suis pas un gars python, alors peut-être pouvez-vous m'aider à ce sujet: cette fonction bombardera-t-elle sur "", là où il n'y en a pas string[0]?
corsiKa
oui, c'est sûr. vous pouvez utiliser (string ou 'x') [0] .isdigit () pour le corriger pour '' ou None
jcomeau_ictx
30
Vous pouvez essayer string[:1].isdigit(), qui quittera heureusement avec une chaîne vide.
Simon Callan
2
parce que ce n'est pas ma réponse; le mien est encore meilleur dans le cas où le programmeur souhaite qu'une exception soit levée sur une chaîne vide.
jcomeau_ictx
1
@jcomeau_ictx exactement ça. ne programmez jamais de manière défensive. si la chaîne est vide de manière inattendue, cela devrait générer une erreur et ne devrait pas être gérée automatiquement de toute façon. Certaines écoles de pensée disent que vous devez gérer et détecter avec élégance les exceptions qui ne sont pas essentielles comme avertissement et maintenir le programme en cours. Je ne suis pas de cet état d'esprit pour la plupart des cas d'utilisation. La spécificité des fonctions et du code que vous écrivez aide à atténuer les cas extrêmes où vous auriez besoin de coder de manière défensive plus souvent.
jamescampbell
10

parfois, vous pouvez utiliser regex

>>> import re
>>> re.search('^\s*[0-9]',"0abc")
<_sre.SRE_Match object at 0xb7722fa8>
Kurumi
la source
exagéré! Pourquoi utiliser re quand vous pouvez le faire dans les bultins
Jakob Bowyer
1
@JakobBowyer Au moins, il est bon de le savoir! Même si dans ce cas, oui, les regex sont exagérées si certaines fonctions intégrées peuvent faire la même chose.
jeromej
8

Votre code ne fonctionnera pas; vous avez besoin orau lieu de ||.

Essayer

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

ou

strg[:1] in '0123456789'

ou, si vous êtes vraiment fou startswith,

strg.startswith(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'))
John Machin
la source
Je vous aurais voté pour s'il n'y avait que la solution avec startswith (un tuple) . Mais les solutions avec strg[:1]ont deux inconvénients: elles ne lèvent pas d'erreur si s peut être une liste de chaînes, et elles produisent True si la chaîne commence par PLUSIEURS chiffres.
eyquem
@eyquem ils produisent True si la chaîne commence par PLUSIEURS chiffres Alors? Les autres réponses ne vérifient pas cela, car il n'était pas obligatoire de vérifier que les autres caractères n'étaient pas numériques.
Rob Grant
Je suis fou startswithet je l' ai implémenté de cette façon dans mon code. Merci.
jamescampbell
Encore un départ avec possibilité ...startswith(tuple(str(i) for i in range(10)))
Jérôme
4

Ce morceau de code:

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

imprime les éléments suivants:

fukushima            False
123 is a number      True
                     False
eyquem
la source
4
C'est moche. Utilisez s[:1].isdigit()ous and s[0].isdigit()
John Machin
1
@John Machin Qu'entendez-vous par «laid»? Illisible ? Je ne trouve pas vos propositions ci-dessus plus lisibles. s and s[0].isdigit()est encore moins lisible à mon avis. Personnellement, j'aime la construction ... si ... sinon ... Compte tenu de votre remarque, je voudrais juste l'améliorer comme ça:s[0].isdigit() if s!="" else False
eyquem
3

Étonnant qu'après si longtemps, il manque encore la meilleure réponse.

L'inconvénient des autres réponses est l'utilisation [0] pour sélectionner le premier caractère, mais comme indiqué, cela casse sur la chaîne vide.

L'utilisation de ce qui suit évite ce problème et, à mon avis, donne la syntaxe la plus jolie et la plus lisible des options dont nous disposons. Il n'import / dérange pas non plus avec regex):

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

>>> string = ''
>>> string[:1].isdigit()
False
PascalVKooten
la source
2

Vous pouvez également utiliser try...except:

try:
    int(string[0])
    # do your stuff
except:
    pass # or do your stuff
Un visage
la source
1

Voici mes "réponses" (en essayant d'être unique ici, je ne recommande pas non plus pour ce cas particulier :-)

En utilisant ord () etla a <= b <= cforme spéciale :

//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'

(Ceci a <= b <= c, comme a < b < c, est une construction Python spéciale et c'est plutôt sympa: comparez 1 < 2 < 3(true) et 1 < 3 < 2(false) et (1 < 3) < 2(true). Ce n'est pas ainsi que cela fonctionne dans la plupart des autres langages.)

En utilisant une expression régulière :

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

la source
1
(1) Perdez le ord()(2) Perdez le ^dans l'expression régulière.
John Machin
0

Vous pouvez utiliser des expressions régulières .

Vous pouvez détecter les chiffres en utilisant:

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

Le par [0-9] correspond à n'importe quel chiffre et votre chaîne [: 1] correspond au premier caractère de votre chaîne

Tovi7
la source
-2

Utilisez des expressions régulières , si vous souhaitez étendre d'une manière ou d'une autre les fonctionnalités de la méthode.

Ilya Smagin
la source
-5

Essaye ça:

if string[0] in range(10):
bradley.ayers
la source
Cela ne fonctionne pas du tout. range(10)produit une liste d'entiers, tandis que string[0]est une chaîne de longueur 1.
Petri Lehtinen
1
Cela ne fonctionne pas; les types ne correspondent pas. Mais: if string[0] in map(str,range(10))fonctionne
phynfo