web-dev-qa-db-fra.com

Python vérifier si les éléments de la liste sont des nombres

J'ai une liste qui contient des chiffres et des lettres au format chaîne.

mylist=['1','orange','2','3','4','Apple']

J'ai besoin de trouver une nouvelle liste qui ne contient que des chiffres:

mynewlist=['1','2','3','4']

Si j'ai un moyen de vérifier si chaque élément de la liste peut être converti en entier, je devrais pouvoir trouver ce que je veux en faisant quelque chose comme ceci:

for item in mylist:
    if (check item can be converted to integer):
        mynewlist.append(item)

Comment puis-je vérifier qu'une chaîne peut être convertie en un entier? Ou existe-t-il une meilleure façon de le faire?

19
Chris Aung

Essaye ça:

mynewlist = [s for s in mylist if s.isdigit()]

De la docs :

str.isdigit()

Renvoie vrai si tous les caractères de la chaîne sont des chiffres et s'il y a au moins un caractère, faux sinon.

Pour les chaînes 8 bits, cette méthode dépend des paramètres régionaux.


Comme indiqué dans les commentaires, isdigit() renvoyant True n'indique pas nécessairement que la chaîne peut être analysée en tant qu'int via la fonction int() et renvoyant False n'indique pas nécessairement qu'il ne peut pas l'être. Néanmoins, l'approche ci-dessus devrait fonctionner dans votre cas.

31
arshajii

Rapide, simple, mais peut-être pas toujours correct:

>>> [x for x in mylist if x.isdigit()]
['1', '2', '3', '4']

Plus traditionnel si vous avez besoin d'obtenir des numéros:

new_list = []
for value in mylist:
    try:
        new_list.append(int(value))
    except ValueError:
        continue

Note: Le résultat a des entiers. Convertissez-les à nouveau en chaînes si nécessaire, en remplaçant les lignes ci-dessus par:

try:
    new_list.append(str(int(value)))
12
Mike Müller

Vous pouvez utiliser une manipulation exceptionnelle comme str.digit ne fonctionnera que pour les entiers et peut également échouer pour quelque chose comme ceci:

>>> str.isdigit(' 1')
False

Utilisation d'une fonction générateur:

def solve(lis):                                        
    for x in lis:
        try:
            yield float(x)
        except ValueError:    
            pass

>>> mylist = ['1','orange','2','3','4','Apple', '1.5', '2.6']
>>> list(solve(mylist))                                    
[1.0, 2.0, 3.0, 4.0, 1.5, 2.6]   #returns converted values

ou peut-être vouliez-vous ceci:

def solve(lis):
    for x in lis:
        try:
            float(x)
            return True
        except:
            return False
...         
>>> mylist = ['1','orange','2','3','4','Apple', '1.5', '2.6']
>>> [x for x in mylist if solve(x)]
['1', '2', '3', '4', '1.5', '2.6']

ou en utilisant ast.literal_eval, cela fonctionnera pour tous les types de numéros:

>>> from ast import literal_eval
>>> def solve(lis):
    for x in lis:
        try:
            literal_eval(x)
            return True
        except ValueError:   
             return False
...         
>>> mylist=['1','orange','2','3','4','Apple', '1.5', '2.6', '1+0j']
>>> [x for x in mylist if solve(x)]                               
['1', '2', '3', '4', '1.5', '2.6', '1+0j']
10

La façon habituelle de vérifier si quelque chose peut être converti en int est de try et de voir, en suivant EAFP principe:

try:
    int_value = int(string_value)
except ValueError:
    # it wasn't an int, do something appropriate
else:
    # it was an int, do something appropriate

Donc, dans votre cas:

for item in mylist:
    try:
        int_value = int(item)
    except ValueError:
        pass
    else:
        mynewlist.append(item) # or append(int_value) if you want numbers

Dans la plupart des cas, une boucle autour d'un code trivial qui se termine par mynewlist.append(item) peut être transformée en une compréhension de liste, une expression de générateur ou un appel à map ou filter. Mais ici, vous ne pouvez pas, car il n'y a aucun moyen de mettre un try/except dans une expression.

Mais si vous l'enveloppez dans une fonction, vous pouvez:

def raises(func, *args, **kw):
    try:
        func(*args, **kw)
    except:
        return True
    else:
        return False

mynewlist = [item for item in mylist if not raises(int, item)]

… Ou, si vous préférez:

mynewlist = filter(partial(raises, int), item)

Il est plus propre de l'utiliser de cette façon:

def raises(exception_types, func, *args, **kw):
    try:
        func(*args, **kw)
    except exception_types:
        return True
    else:
        return False

De cette façon, vous pouvez lui passer l'exception (ou Tuple d'exceptions) que vous attendez, et ceux-ci renverront True, mais le cas échéant inattendu des exceptions sont levées, elles se propageront. Alors:

mynewlist = [item for item in mylist if not raises(ValueError, int, item)]

… Fera ce que vous voulez, mais:

mynewlist = [item for item in mylist if not raises(ValueError, item, int)]

… Lèvera un TypeError, comme il se doit.

4
abarnert