Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way to eval all octal values in a string as integers

So I've got a string that looks like "012 + 2 - 01 + 24" for example. I want to be able to quickly (less code) evaluate that expression...

I could use eval() on the string, but I don't want 012 to be represented in octal form (10), I want it to be represented as an int (12).

My solution for this works, but it is not elegant. I am sort of assuming that there is a really good pythonic way to do this.

My solution:

#expression is some string that looks like "012 + 2 - 01 + 24"
atomlist = []
for atom in expression.split():
    if "+" not in atom and "-" not in atom:
        atomlist.append(int(atom))
    else:
        atomlist.append(atom)
#print atomlist
evalstring = ""
for atom in atomlist:
    evalstring+=str(atom)    
#print evalstring
num = eval(evalstring)

Basically, I tear appart the string, and find numbers in it and turn them into ints, and then I rebuild the string with the ints (essentially removing leading 0's except where 0 is a number on its own).

How can this be done better?

like image 720
Dream Lane Avatar asked Mar 23 '12 16:03

Dream Lane


2 Answers

I'd be tempted to use regular expressions to remove the leading zeroes:

>>> re.sub(r'\b0+(?!\b)', '', '012 + 2 + 0 - 01 + 204 - 0')
'12 + 2 + 0 - 1 + 204 - 0'

This removes zeroes at the start of every number, except when the number consists entirely of zeroes:

  • the first \b matches a word (token) boundary;
  • the 0+ matches one or more consecutive zeroes;
  • the (?!\b) (negative lookahead) inhibits matches where the sequence of zeroes is followed by a token boundary.

One advantage of this approach over split()-based alternatives is that it doesn't require spaces in order to work:

>>> re.sub(r'\b0+(?!\b)', '', '012+2+0-01+204-0')
'12+2+0-1+204-0'
like image 170
NPE Avatar answered Oct 14 '22 01:10

NPE


You can do this in one line using lstrip() to strip off any leading zeros:

>>> eval("".join(token.lstrip('0') for token in s.split()))
37
like image 5
grifaton Avatar answered Oct 14 '22 01:10

grifaton