Question

    

Cette question a déjà une réponse ici:

    
            
  •              flotteur Extrait / valeur double                                      4 réponses                          
  •     
    

J'ai un certain nombre de chaînes semblables à Current Level: 13.4 db. et je voudrais extraire seulement le nombre à virgule flottante. Je dis flottante et non décimal il est parfois tout. Can RegEx faire ceci ou est-il un moyen de mieux?

Était-ce utile?

La solution

Si votre flotteur est toujours exprimé quelque chose comme la notation décimale

>>> import re
>>> re.findall("\d+\.\d+", "Current Level: 13.4 db.")
['13.4']

peut suffire.

Une version plus robuste serait:

>>> re.findall(r"[-+]?\d*\.\d+|\d+", "Current Level: -13.2 db or 14.2 or 3")
['-13.2', '14.2', '3']

Si vous voulez entrée utilisateur de validation, vous pouvez encore vérifier aussi pour un flotteur en marchant directement à:

user_input = "Current Level: 1e100 db"
for token in user_input.split():
    try:
        # if this succeeds, you have your (first) float
        print float(token), "is a float"
    except ValueError:
        print token, "is something else"

# => Would print ...
#
# Current is something else
# Level: is something else
# 1e+100 is a float
# db is something else

Autres conseils

Vous pouvez vous essayer quelque chose comme ce qui couvre toutes les bases, y compris ne pas compter sur les espaces après le numéro:

>>> import re
>>> numeric_const_pattern = r"""
...     [-+]? # optional sign
...     (?:
...         (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc
...         |
...         (?: \d+ \.? ) # 1. 12. 123. etc 1 12 123 etc
...     )
...     # followed by optional exponent part if desired
...     (?: [Ee] [+-]? \d+ ) ?
...     """
>>> rx = re.compile(numeric_const_pattern, re.VERBOSE)
>>> rx.findall(".1 .12 9.1 98.1 1. 12. 1 12")
['.1', '.12', '9.1', '98.1', '1.', '12.', '1', '12']
>>> rx.findall("-1 +1 2e9 +2E+09 -2e-9")
['-1', '+1', '2e9', '+2E+09', '-2e-9']
>>> rx.findall("current level: -2.03e+99db")
['-2.03e+99']
>>>

Pour copier-coller facilement:

numeric_const_pattern = '[-+]? (?: (?: \d* \. \d+ ) | (?: \d+ \.? ) )(?: [Ee] [+-]? \d+ ) ?'
rx = re.compile(numeric_const_pattern, re.VERBOSE)
rx.findall("Some example: Jr. it. was .23 between 2.3 and 42.31 seconds")

Python docs a une réponse qui couvre +/- et exposant la notation

scanf() Token      Regular Expression
%e, %E, %f, %g     [-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?
%i                 [-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)

Cette expression régulière ne prend pas en charge les formats internationaux où une virgule est utilisé comme séparateur entre la partie entière et fractionnaire (3,14159). Dans ce cas, remplacer tous \. avec [.,] dans le regex flottent au-dessus.

                        Regular Expression
International float     [-+]?(\d+([.,]\d*)?|[.,]\d+)([eE][-+]?\d+)?
re.findall(r"[-+]?\d*\.?\d+|\d+", "Current Level: -13.2 db or 14.2 or 3")

comme décrit ci-dessus, fonctionne très bien! Une suggestion cependant:

re.findall(r"[-+]?\d*\.?\d+|[-+]?\d+", "Current Level: -13.2 db or 14.2 or 3 or -3")

sera également renvoyer des valeurs négatives int (comme -3 à la fin de cette chaîne)

Vous pouvez utiliser l'expression rationnelle suivante pour obtenir des valeurs flottantes et entier à partir d'une chaîne:

re.findall(r'[\d\.\d]+', 'hello -34 42 +34.478m 88 cricket -44.3')

['34', '42', '34.478', '88', '44.3']

Merci Rex

Je pense que vous trouverez des choses intéressantes dans la réponse suivante à moi que je l'ai fait pour une précédente question similaire:

https://stackoverflow.com/q/5929469/551449

Dans cette réponse, je propose un modèle qui permet une expression régulière pour attraper tout type de nombre et que je n'ai rien d'autre à ajouter, je pense qu'il est assez complet

Une autre approche qui peut être plus facile à lire est la conversion de type simple. J'ai ajouté une fonction de remplacement aux instances de couverture où les gens peuvent entrer des décimales européennes:

>>> for possibility in "Current Level: -13.2 db or 14,2 or 3".split():
...     try:
...         str(float(possibility.replace(',', '.')))
...     except ValueError:
...         pass
'-13.2'
'14.2'
'3.0'

présente des inconvénients trop cependant. Si quelqu'un tape « 1000 », ce sera converti en 1. Il suppose également que les gens seront SAISIE avec un espace entre les mots. Ce n'est pas le cas avec d'autres langues, comme le chinois.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top