Stefan Badertscher
Stefan Badertscher

Reputation: 341

How to find a pair of numbers between parentheses using a regular expression?

I have the following string with some text / numbers in it. There is always a () with two numbers in between. These two numbers need to be extracted. The string looks like this:

s = 'sadfdaf dsf4as d a4d34s ddfd (54.4433,-112.3554) a45 6sd 6f8 asdf'

I need a regular expression for solving that. Pseudo code like this

  1. search s for ( and check if number is next char

  2. Extract numbers until ,

  3. Extract second number until )

I found the following solution from stackoverflow

print re.findall("[-+]?\d+[\.]?\d*[eE]?[-+]?\d*", schoolAddressString) 

which returns: ['4', '4', '34', '54.4433', '-112.3554', '45', '6', '6', '8']

So I need to have this expression to only consider numbers between () with something like^( and $(.

How is this done exactly?

Upvotes: 2

Views: 2852

Answers (3)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

You could simply use a regex to capture the elements between brackets, and then parse these using .split(',') and float to parse them to floats. Like:

for match in re.findall(r'(?<=\().*?(?=\))',schoolAddressString):
    a,b = map(float,match.split(','))
    # do something with a and b, for example
    print([a,b])

This prints:

>>> for match in re.findall(r'(?<=\().*?(?=\))',schoolAddressString):
...     a,b = map(float,match.split(','))
...     # do something with a and b, for example
...     print([a,b])
... 
[54.4433, -112.3554]

Furthermore here you parse a float. Therefore I think that the parsing will be less error prone: there will be more patterns that can be parsed, and the parsing is probably done correctly.

The result of the map(..) is a list. So in case there can be an arbitrary number of values between the brackets, you can use values = map(..) and then process the elements in values.

Float pattern

The pattern the float(..) constructor can parse is described in the documentation:

sign           ::=  "+" | "-"
infinity       ::=  "Infinity" | "inf"
nan            ::=  "nan"
numeric_value  ::=  floatnumber | infinity | nan
numeric_string ::=  [sign] numeric_value

floatnumber     ::=  pointfloat | exponentfloat
pointfloat      ::=  [digitpart] fraction | digitpart "."
exponentfloat   ::=  (digitpart | pointfloat) exponent
digitpart       ::=  digit (["_"] digit)*
fraction        ::=  "." digitpart
exponent        ::=  ("e" | "E") ["+" | "-"] digitpart

digit           ::=  "0"..."9"

So the "added" value of using the constructor is that underscores are allowed as well (to separate groups of digits), and furthermore values like infinity, inf and nan are also allowed.

Upvotes: 6

trapuck
trapuck

Reputation: 43

If you're variable s is a string you can use the split method (docs python) You can make a code like that :

s = 'sadfdaf dsf4as d a4d34s ddfd (54.4433,-112.3554) a45 6sd 6f8 asdf'
s_without_beginning = s.split('(')[1]
s_without_extremeties = s_without_beginning.split(')')[0]
numbers = s_without_extremeties.split(',')

This will return :

numbers =

['54.4433', '-112.3554']

But you have to be sure the separators are always ( , )

Upvotes: 2

Scott Hunter
Scott Hunter

Reputation: 49813

Something like this?

for segment in re.findall("[(][^)]*[)]", s):
    print re.findall("[-+]?\d+[\.]?\d*[eE]?[-+]?\d*", segment) 

Note that this works no matter how many numbers are in each segment, or how they are separated, which is more flexible than it sounds like you need.

Upvotes: 4

Related Questions