Hoe getallen uit een string halen in Python?

Ik wil graag alle getallen in een string extraheren. Wat is beter geschikt voor het doel, reguliere expressies of de isdigit()methode?

Voorbeeld:

line = "hello 12 hi 89"

Resultaat:

[12, 89]

Antwoord 1, autoriteit 100%

Als je alleen positieve gehele getallen wilt extraheren, probeer dan het volgende:

>>> txt = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in txt.split() if s.isdigit()]
[23, 11, 2]

Ik zou zeggen dat dit beter is dan het regex-voorbeeld, omdat je geen andere module nodig hebt en het is beter leesbaar omdat je de regex mini-taal.

Hiermee worden geen floats, negatieve gehele getallen of gehele getallen in hexadecimaal formaat herkend. Als u deze beperkingen niet kunt accepteren, het antwoord van jmnas hieronderzal het lukken.


Antwoord 2, autoriteit 93%

Ik zou een regexp gebruiken:

>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']

Dit komt ook overeen met 42 van bla42bla. Als u alleen getallen wilt die worden gescheiden door woordgrenzen (spatie, punt, komma), kunt u \b :

gebruiken

>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']

Om te eindigen met een lijst met getallen in plaats van een lijst met strings:

>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]

Antwoord 3, autoriteit 16%

Dit is meer dan een beetje laat, maar je kunt de regex-expressie uitbreiden om ook rekening te houden met wetenschappelijke notatie.

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)

Geeft alles goed!

Bovendien kunt u de AWS Lijm ingebouwde regex


Antwoord 4, autoriteit 13%

Ik neem aan dat je floats wilt, niet alleen gehele getallen, dus ik zou zoiets als dit doen:

l = []
for t in s.split():
    try:
        l.append(float(t))
    except ValueError:
        pass

Merk op dat sommige van de andere oplossingen die hier zijn geplaatst, niet werken met negatieve getallen:

>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string -30')
['42', '32', '30']
>>> '-3'.isdigit()
False

Antwoord 5, Autoriteit 12%

Als u weet dat het slechts één nummer in de tekenreeks is, d.w.z.e 'hello 12 hi', kunt u filterproberen.

Bijvoorbeeld:

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

maar wees voorzichtig !!! :

In [4]: int(''.join(filter(str.isdigit, '200 grams 5')))
Out[4]: 2005

Antwoord 6, Autoriteit 4%

Ik was op zoek naar een oplossing om de maskers van de snaren te verwijderen, met name uit Braziliaanse telefoons nummers, deze post niet beantwoord, maar inspireerde me. Dit is mijn oplossing:

>>> phone_number = '+55(11)8715-9877'
>>> ''.join([n for n in phone_number if n.isdigit()])
'551187159877'

Antwoord 7, Autoriteit 3%

Om verschillende patronen te vangen, is het handig om met verschillende patronen te vragen.

Instellen alle patronen die verschillende nummers van belangstelling vangen:

(Vind komma’s) 12.300 of 12.300.00

‘[\ d] + [., \ d] +’

(vindt drijvers) 0,123 of .123

‘[\d]*[.][\d]+’

(vindt gehele getallen) 123

‘[\d]+’

Combineer met pijp ( | ) tot één patroon met meerdere of voorwaarden.

(Opmerking: zet eerst complexe patronen, anders zullen eenvoudige patronen delen van de complexe vangst retourneren in plaats van de complexe vangst die de volledige vangst retourneert).

p = '[\d]+[.,\d]+|[\d]*[.][\d]+|[\d]+'

Hieronder zullen we bevestigen dat er een patroon aanwezig is met re.search(), en vervolgens een itereerbare lijst van vangsten retourneren. Ten slotte zullen we elke vangst afdrukken met behulp van haakjesnotatie om de retourwaarde van het wedstrijdobject uit het wedstrijdobject te subselecteren.

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

Retouren:

33
42
32
30
444.4
12,001

Antwoord 8, autoriteit 3%

# 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]

Antwoord 9, autoriteit 3%

Het gebruik van onderstaande Regex is de manier

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)

met 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']

Antwoord 10, autoriteit 3%

Voor telefoonnummers kunt u eenvoudig alle niet-cijferige tekens uitsluiten met \Din regex:

import re
phone_number = "(619) 459-3635"
phone_number = re.sub(r"\D", "", phone_number)
print(phone_number)

De rin r"\D"staat voor onbewerkte tekenreeks. Het is nodig. Zonder dit zal Python \Dbeschouwen als een escape-teken.


Antwoord 11

line2 = "hello 12 hi 89"  # this is the given string 
temp1 = re.findall(r'\d+', line2) # find number of digits through regular expression
res2 = list(map(int, temp1))
print(res2)

Hallo,

u kunt alle gehele getallen in de tekenreeks doorzoeken met behulp van de uitdrukking findall .

Maak in de tweede stap een lijst res2 en voeg de gevonden cijfers in string toe aan deze lijst

hoop dat dit helpt

Met vriendelijke groet,
Diwakar Sharma


Antwoord 12

Dit antwoord bevat ook het geval wanneer het getal in de tekenreeks zweeft

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)

Antwoord 13

Ik voeg dit antwoord gewoon toe omdat niemand er een heeft toegevoegd met Exception handling en omdat dit ook werkt voor floats

a = []
line = "abcd 1234 efgh 56.78 ij"
for word in line.split():
    try:
        a.append(float(word))
    except ValueError:
        pass
print(a)

Uitvoer:

[1234.0, 56.78]

Antwoord 14

Het verbaast me dat nog niemand het gebruik van itertools.groupbyals alternatief om dit te bereiken.

Je mag itertools.groupby()samen met str.isdigit()om getallen uit een string te halen als:

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]

De waarde die wordt vastgehouden door lis:

[12, 89]

PS: Dit is gewoon voor illustratie Doel om te laten zien dat als alternatief we ook groupbygebruiken om dit te bereiken. Maar dit is geen aanbevolen oplossing. Als u dit wilt bereiken, zou u moeten gebruiken Geaccepteerd antwoord van Fmark op basis van het begrijpen van lijstbegrip met str.isdigitALS FILTER.


Antwoord 15

@jmnas, ik vond je antwoord leuk, maar het vond geen drijvers. Ik werk aan een script om de code te ontleden die naar een CNC-molen gaan en nodig is om zowel X- als Y-dimensies te vinden die gehele getallen of drijvers kunnen zijn, dus ik heb uw code aan het volgende aangepast. Dit vindt int, drijft met positieve en negatieve vals. Nog steeds vindt de hex-geformatteerde waarden niet, maar u kunt “X” en “A” via “F” toevoegen aan de num_chartuple en ik denk dat het dingen als ‘0x23ac’ zou ontleden.

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)

Antwoord 16

Aangezien geen van deze financiële nummers van de echte wereld in Excel en Word Docs die ik moest vinden, is hier mijn variatie. Het behandelt inten, drijvers, negatieve nummers, valuta-nummers (omdat het niet op splitsing antwoordt), en de optie heeft om het decimale deel te laten vallen en gewoon ints terug te sturen of alles terug te keren.

Het behandelt ook het Indiase Laks-nummersysteem waar komma’s onregelmatig lijken, niet elke 3 nummers uit elkaar.

Het verwerkt geen wetenschappelijke notatie of negatieve getallen tussen haakjes in budgetten — zullen positief lijken.

Het haalt ook geen datums uit. Er zijn betere manieren om datums in strings te vinden.

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

Antwoord 17

De beste optie die ik heb gevonden, staat hieronder. Het zal een getal extraheren en kan elk type teken elimineren.

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)    

Other episodes