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?
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.
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)))
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']
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.