Réponses:
Si vous souhaitez uniquement extraire uniquement des entiers positifs, essayez ce qui suit:
>>> str = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in str.split() if s.isdigit()]
[23, 11, 2]
Je dirais que c'est mieux que l'exemple regex pour trois raisons. Tout d'abord, vous n'avez pas besoin d'un autre module; deuxièmement, il est plus lisible car vous n'avez pas besoin d'analyser le mini-langage regex; et troisièmement, il est plus rapide (et donc probablement plus pythonique):
python -m timeit -s "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "[s for s in str.split() if s.isdigit()]"
100 loops, best of 3: 2.84 msec per loop
python -m timeit -s "import re" "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "re.findall('\\b\\d+\\b', str)"
100 loops, best of 3: 5.66 msec per loop
Cela ne reconnaîtra pas les flottants, les entiers négatifs ou les entiers au format hexadécimal. Si vous ne pouvez pas accepter ces limitations, la réponse de slim ci - dessous fera l'affaire.
re
. C'est un outil général et puissant (vous apprenez donc quelque chose de très utile). La vitesse est quelque peu hors de propos dans l'analyse des journaux (ce n'est pas un solveur numérique intensif après tout), le re
module est dans la bibliothèque Python standard et cela ne fait pas de mal de le charger.
mumblejumble45mumblejumble
dans lesquelles je savais qu'il n'y avait qu'un seul numéro. La solution est simple int(filter(str.isdigit, your_string))
.
str
qui remplace alors l' str
objet et la méthode en python de base. Ce n'est pas une bonne pratique car vous en aurez peut-être besoin plus tard dans le script.
int(filter(...))
augmentera TypeError: int() argument must be a string...
pour Python 3.5, vous pouvez donc utiliser la version mise à jour: int(''.join(filter(str.isdigit, your_string)))
pour extraire tous les chiffres en un seul entier.
J'utiliserais une expression rationnelle:
>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']
Cela correspondrait également à 42 de bla42bla
. Si vous souhaitez uniquement des nombres délimités par des limites de mots (espace, point, virgule), vous pouvez utiliser \ b:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']
Pour finir avec une liste de nombres au lieu d'une liste de chaînes:
>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]
int
dessus et vous avez terminé. +1 surtout pour la dernière partie. Je suggère cependant des chaînes brutes ( r'\b\d+\b' == '\\b\\d+\\b'
).
int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]
map
.
C'est plus qu'un peu en retard, mais vous pouvez également étendre l'expression régulière pour tenir compte de la notation scientifique.
import re
# Format is [(<string>, <expected output>), ...]
ss = [("apple-12.34 ba33na fanc-14.23e-2yapple+45e5+67.56E+3",
['-12.34', '33', '-14.23e-2', '+45e5', '+67.56E+3']),
('hello X42 I\'m a Y-32.35 string Z30',
['42', '-32.35', '30']),
('he33llo 42 I\'m a 32 string -30',
['33', '42', '32', '-30']),
('h3110 23 cat 444.4 rabbit 11 2 dog',
['3110', '23', '444.4', '11', '2']),
('hello 12 hi 89',
['12', '89']),
('4',
['4']),
('I like 74,600 commas not,500',
['74,600', '500']),
('I like bad math 1+2=.001',
['1', '+2', '.001'])]
for s, r in ss:
rr = re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?", s)
if rr == r:
print('GOOD')
else:
print('WRONG', rr, 'should be', r)
Donne tout bon!
En outre, vous pouvez consulter l' expression régulière intégrée AWS Glue
s = "4"
ne renvoie aucune correspondance. Peut-il être modifié pour prendre également en charge cela?
[+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)?
Ce groupe donne des faux positifs (c'est-à +
- dire qu'il est parfois capturé par lui-même), mais est capable de gérer plus de formulaires, comme .001
, plus il ne combine pas automatiquement les nombres (comme dans s=2+1
)
[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?
- si stupide de moi ... comment pourrais-je ne pas penser à cela?
Je suppose que vous voulez des flottants et pas seulement des entiers, alors je ferais quelque chose comme ceci:
l = []
for t in s.split():
try:
l.append(float(t))
except ValueError:
pass
Notez que certaines des autres solutions publiées ici ne fonctionnent pas avec des nombres négatifs:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string -30')
['42', '32', '30']
>>> '-3'.isdigit()
False
float
à int
.
re.findall("[-\d]+", "1 -2")
continue
au lieu de pass
dans la boucle?
Si vous savez qu'il n'y aura qu'un seul numéro dans la chaîne, c'est-à-dire «bonjour 12 salut», vous pouvez essayer de filtrer.
Par exemple:
In [1]: int(''.join(filter(str.isdigit, '200 grams')))
Out[1]: 200
In [2]: int(''.join(filter(str.isdigit, 'Counters: 55')))
Out[2]: 55
In [3]: int(''.join(filter(str.isdigit, 'more than 23 times')))
Out[3]: 23
Mais attention !!! :
In [4]: int(''.join(filter(str.isdigit, '200 grams 5')))
Out[4]: 2005
TypeError: int() argument must be a string, a bytes-like object or a number, not 'filter'
- réparé en utilisantint("".join(filter(str.isdigit, '200 grams')))
# extract numbers from garbage string:
s = '12//n,_@#$%3.14kjlw0xdadfackvj1.6e-19&*ghn334'
newstr = ''.join((ch if ch in '0123456789.-e' else ' ') for ch in s)
listOfNumbers = [float(i) for i in newstr.split()]
print(listOfNumbers)
[12.0, 3.14, 0.0, 1.6e-19, 334.0]
Je cherchais une solution pour supprimer les masques de chaînes, en particulier des numéros de téléphone brésiliens, ce message n'a pas répondu mais m'a inspiré. Voici ma solution:
>>> phone_number = '+55(11)8715-9877'
>>> ''.join([n for n in phone_number if n.isdigit()])
'551187159877'
Utiliser Regex ci-dessous est le moyen
lines = "hello 12 hi 89"
import re
output = []
#repl_str = re.compile('\d+.?\d*')
repl_str = re.compile('^\d+$')
#t = r'\d+.?\d*'
line = lines.split()
for word in line:
match = re.search(repl_str, word)
if match:
output.append(float(match.group()))
print (output)
avec findall
re.findall(r'\d+', "hello 12 hi 89")
['12', '89']
re.findall(r'\b\d+\b', "hello 12 hi 89 33F AC 777")
['12', '89', '777']
findall()
repl_str = re.compile('\d+.?\d*')
devrait être: repl_str = re.compile('\d+\.?\d*')
Pour un exemple reproductible en utilisant python3.7 re.search(re.compile(r'\d+.?\d*'), "42G").group()
'42G' re.search(re.compile(r'\d+\.?\d*'), "42G").group()
'42'
line2 = "hello 12 hi 89"
temp1 = re.findall(r'\d+', line2) # through regular expression
res2 = list(map(int, temp1))
print(res2)
Salut ,
vous pouvez rechercher tous les entiers de la chaîne à travers chiffre en utilisant l'expression findall.
Dans la deuxième étape, créez une liste res2 et ajoutez les chiffres trouvés dans la chaîne à cette liste
J'espère que cela t'aides
Cordialement, Diwakar Sharma
Cette réponse contient également le cas où le nombre est flottant dans la chaîne
def get_first_nbr_from_str(input_str):
'''
:param input_str: strings that contains digit and words
:return: the number extracted from the input_str
demo:
'ab324.23.123xyz': 324.23
'.5abc44': 0.5
'''
if not input_str and not isinstance(input_str, str):
return 0
out_number = ''
for ele in input_str:
if (ele == '.' and '.' not in out_number) or ele.isdigit():
out_number += ele
elif out_number:
break
return float(out_number)
Je suis étonné de voir que personne n’a encore mentionné l’utilisation de itertools.groupby
comme alternative pour y parvenir.
Vous pouvez utiliser itertools.groupby()
avec str.isdigit()
pour extraire des nombres de la chaîne comme:
from itertools import groupby
my_str = "hello 12 hi 89"
l = [int(''.join(i)) for is_digit, i in groupby(my_str, str.isdigit) if is_digit]
La valeur détenue par l
sera:
[12, 89]
PS: Ceci est juste à des fins d'illustration pour montrer que nous pouvons également utiliser une alternative groupby
pour y parvenir. Mais ce n'est pas une solution recommandée. Si vous voulez y parvenir, vous devez utiliser la réponse acceptée de fmark basée sur l'utilisation de la compréhension de liste avec str.isdigit
comme filtre.
J'ajoute simplement cette réponse parce que personne n'en a ajouté une en utilisant la gestion des exceptions et parce que cela fonctionne également pour les flottants
a = []
line = "abcd 1234 efgh 56.78 ij"
for word in line.split():
try:
a.append(float(word))
except ValueError:
pass
print(a)
Production :
[1234.0, 56.78]
Pour capturer différents modèles, il est utile d'interroger avec différents modèles.
«[\ d] + [., \ d] +»
«[\ d] * [.] [\ d] +»
«[\ d] +»
(Remarque: Mettez les modèles complexes en premier sinon les modèles simples renverront des morceaux de la capture complexe au lieu de la capture complexe renvoyant la capture complète).
p = '[\d]+[.,\d]+|[\d]*[.][\d]+|[\d]+'
Ci-dessous, nous confirmerons la présence d'un modèle re.search()
, puis retournerons une liste itérable des captures. Enfin, nous imprimerons chaque capture en utilisant la notation entre crochets pour sous-sélectionner la valeur de retour de l'objet de correspondance à partir de l'objet de correspondance.
s = 'he33llo 42 I\'m a 32 string 30 444.4 12,001'
if re.search(p, s) is not None:
for catch in re.finditer(p, s):
print(catch[0]) # catch is a match object
Retour:
33
42
32
30
444.4
12,001
Puisqu'aucune de celles-ci ne traitait de chiffres financiers réels dans des documents Excel et Word que je devais trouver, voici ma variation. Il gère les ints, les flottants, les nombres négatifs, les numéros de devise (car il ne répond pas en cas de fractionnement), et a la possibilité de supprimer la partie décimale et de simplement retourner les ints, ou tout renvoyer.
Il gère également le système de numérotation Indian Laks où les virgules apparaissent irrégulièrement, pas tous les 3 nombres.
Il ne gère pas la notation scientifique ou les nombres négatifs mis entre parenthèses dans les budgets - apparaîtra positif.
Il n'extrait pas non plus de dates. Il existe de meilleures façons de rechercher des dates dans des chaînes.
import re
def find_numbers(string, ints=True):
numexp = re.compile(r'[-]?\d[\d,]*[\.]?[\d{2}]*') #optional - in front
numbers = numexp.findall(string)
numbers = [x.replace(',','') for x in numbers]
if ints is True:
return [int(x.replace(',','').split('.')[0]) for x in numbers]
else:
return numbers
@jmnas, j'ai aimé votre réponse, mais elle n'a pas trouvé de flotteurs. Je travaille sur un script pour analyser le code allant à une fraiseuse CNC et j'avais besoin de trouver les dimensions X et Y qui peuvent être des entiers ou des flottants, j'ai donc adapté votre code aux éléments suivants. Cela trouve int, float avec des valeurs positives et négatives. Ne trouve toujours pas de valeurs au format hexadécimal, mais vous pouvez ajouter "x" et "A" à "F" au num_char
tuple et je pense que cela analyserait des choses comme '0x23AC'.
s = 'hello X42 I\'m a Y-32.35 string Z30'
xy = ("X", "Y")
num_char = (".", "+", "-")
l = []
tokens = s.split()
for token in tokens:
if token.startswith(xy):
num = ""
for char in token:
# print(char)
if char.isdigit() or (char in num_char):
num = num + char
try:
l.append(float(num))
except ValueError:
pass
print(l)
La meilleure option que j'ai trouvée est ci-dessous. Il extraira un nombre et peut éliminer tout type de caractère.
def extract_nbr(input_str):
if input_str is None or input_str == '':
return 0
out_number = ''
for ele in input_str:
if ele.isdigit():
out_number += ele
return float(out_number)
Pour les numéros de téléphone, vous pouvez simplement exclure tous les caractères non numériques avec \ D dans l'expression régulière:
import re
phone_number = '(619) 459-3635'
phone_number = re.sub(r"\D", "", phone_number)
print(phone_number)