Je voudrais extraire tous les nombres contenus dans une chaîne. Quelle est la mieux adaptée à la fin, aux expressions régulières ou à laisdigit()
méthode?
Exemple:
line = "hello 12 hi 89"
Résultat:
[12, 89]
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), lere
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 simpleint(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(...))
augmenteraTypeError: 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:
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:Pour finir avec une liste de nombres au lieu d'une liste de chaînes:
la source
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.
Donne tout bon!
En outre, vous pouvez consulter l' expression régulière intégrée AWS Glue
la source
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 danss=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:
Notez que certaines des autres solutions publiées ici ne fonctionnent pas avec des nombres négatifs:
la source
float
àint
.re.findall("[-\d]+", "1 -2")
continue
au lieu depass
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:
Mais attention !!! :
la source
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')))
la source
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:
la source
Utiliser Regex ci-dessous est le moyen
avec findall
re.findall(r'\d+', "hello 12 hi 89")
re.findall(r'\b\d+\b', "hello 12 hi 89 33F AC 777")
la source
findall()
repl_str = re.compile('\d+.?\d*')
devrait être:repl_str = re.compile('\d+\.?\d*')
Pour un exemple reproductible en utilisant python3.7re.search(re.compile(r'\d+.?\d*'), "42G").group()
'42G're.search(re.compile(r'\d+\.?\d*'), "42G").group()
'42'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
la source
Cette réponse contient également le cas où le nombre est flottant dans la chaîne
la source
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()
avecstr.isdigit()
pour extraire des nombres de la chaîne comme:La valeur détenue par
l
sera: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 avecstr.isdigit
comme filtre.la source
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
Production :
la source
Pour capturer différents modèles, il est utile d'interroger avec différents modèles.
Configurez tous les modèles qui captent différents modèles de nombres d'intérêt:
(trouve les virgules) 12 300 ou 12 300,00
«[\ d] + [., \ d] +»
(trouve des flotteurs) 0,123 ou 0,123
«[\ d] * [.] [\ d] +»
(trouve des entiers) 123
«[\ d] +»
Combinez avec le tuyau (|) en un seul motif avec plusieurs ou conditionnels .
(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).
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.Retour:
la source
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.
la source
@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'.la source
La meilleure option que j'ai trouvée est ci-dessous. Il extraira un nombre et peut éliminer tout type de caractère.
la source
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:
la source