I would extract all the numbers contained in a string. Which is the better suited for the purpose, regular expressions or the `isdigit()`

method?

Example:

line = "hello 12 hi 89"

Result:

[12, 89]

Skip to content
# regex – How to extract numbers from a string in Python?

## The Question :

*485 people think this question is useful*
*The Question Comments :*
## The Answer 1

*548 people think this answer is useful*
## The Answer 2

*508 people think this answer is useful*
## The Answer 3

*94 people think this answer is useful*
## The Answer 4

*73 people think this answer is useful*
## The Answer 5

*71 people think this answer is useful*
## The Answer 6

*19 people think this answer is useful*
## The Answer 7

*18 people think this answer is useful*
## The Answer 8

*14 people think this answer is useful*
## The Answer 9

*13 people think this answer is useful*
## Setup all the patterns that catch different number patterns of interest:

### (finds commas) 12,300 or 12,300.00

### (finds floats) 0.123 or .123

### (finds integers) 123

## Combine with pipe ( | ) into one pattern with multiple *or conditionals*.

## The Answer 10

*9 people think this answer is useful*
## The Answer 11

*8 people think this answer is useful*
## The Answer 12

*7 people think this answer is useful*
## The Answer 13

*5 people think this answer is useful*
## The Answer 14

*5 people think this answer is useful*
## The Answer 15

*2 people think this answer is useful*
## The Answer 16

*1 people think this answer is useful*
## The Answer 17

*0 people think this answer is useful*

2021-01-13

I would extract all the numbers contained in a string. Which is the better suited for the purpose, regular expressions or the `isdigit()`

method?

Example:

line = "hello 12 hi 89"

Result:

[12, 89]

- Unfortunately the sample input data was so simplistic, since such invited naive solutions. Common cases should handle input strings with more interesting characters adjacent to the digits. A slightly more challenging input:
`'''gimme digits from "12", 34, '56', -789.'''`

If you only want to extract only positive integers, try the following:

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

I would argue that this is better than the regex example because you don’t need another module and it’s more readable because you don’t need to parse (and learn) the regex mini-language.

This will not recognize floats, negative integers, or integers in hexadecimal format. If you can’t accept these limitations, jmnas’s answer below will do the trick.

I’d use a regexp :

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

This would also match 42 from `bla42bla`

. If you only want numbers delimited by word boundaries (space, period, comma), you can use \b :

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

To end up with a list of numbers instead of a list of strings:

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

This is more than a bit late, but you can extend the regex expression to account for scientific notation too.

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)

Gives all good!

Additionally, you can look at the AWS Glue built-in regex

I’m assuming you want floats not just integers so I’d do something like this:

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

Note that some of the other solutions posted here don’t work with negative numbers:

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

If you know it will be only one number in the string, i.e `'hello 12 hi'`

, you can try `filter`

.

For example:

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

But be carefull !!! :

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

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

I was looking for a solution to remove strings’ masks, specifically from Brazilian phones numbers, this post not answered but inspired me. This is my solution:

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

Using Regex below is the way

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)

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

To catch different patterns it is helpful to query with different patterns.

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

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

‘[\d]+’

*(Note: Put complex patterns first else simple patterns will return chunks of the complex catch instead of the complex catch returning the full catch).*

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

Below, we’ll confirm a pattern is present with `re.search()`

, then return an iterable list of catches. Finally, we’ll print each catch using bracket notation to subselect the match object return value from the match object.

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

Returns:

33 42 32 30 444.4 12,001

line2 = "hello 12 hi 89" temp1 = re.findall(r'\d+', line2) # through regular expression res2 = list(map(int, temp1)) print(res2)

Hi ,

you can search all the integers in the string through digit by using findall expression .

In the second step create a list res2 and add the digits found in string to this list

hope this helps

Regards, Diwakar Sharma

For phone numbers you can simply exclude all non-digit characters with \D in regex:

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

This answer also contains the case when the number is float in the string

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)

I am amazed to see that no one has yet mentioned the usage of ** itertools.groupby** as an alternative to achieve this.

You may use `itertools.groupby()`

along with `str.isdigit()`

in order to extract numbers from string as:

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]

The value hold by `l`

will be:

[12, 89]

** PS:** This is just for illustration purpose to show that as an alternative we could also use

`groupby`

to achieve this. But this is not a recommended solution. If you want to achieve this, you should be using accepted answer of fmark based on using list comprehension with `str.isdigit`

as filter.I am just adding this answer because no one added one using Exception handling and because this also works for floats

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

Output :

[1234.0, 56.78]

Since none of these dealt with real world financial numbers in excel and word docs that I needed to find, here is my variation. It handles ints, floats, negative numbers, currency numbers (because it doesn’t reply on split), and has the option to drop the decimal part and just return ints, or return everything.

It also handles Indian Laks number system where commas appear irregularly, not every 3 numbers apart.

It does not handle scientific notation or negative numbers put inside parentheses in budgets — will appear positive.

It also does not extract dates. There are better ways for finding dates in strings.

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, I liked your answer, but it didn’t find floats. I’m working on a script to parse code going to a CNC mill and needed to find both X and Y dimensions that can be integers or floats, so I adapted your code to the following. This finds int, float with positive and negative vals. Still doesn’t find hex formatted values but you could add “x” and “A” through “F” to the `num_char`

tuple and I think it would parse things like ‘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)

The best option I found is below. It will extract a number and can eliminate any type of char.

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)