views:

360

answers:

6

I have strings which look like this one:

"(8, 12.25), (13, 15), (16.75, 18.5)"

and I would like to convert each of them into a python data structure. Preferably a list (or tuple) of tuples containing a pair of float values.

I could do that with eval("(8, 12.25), (13, 15), (16.75, 18.5)") which gives me a tuple of tuples, but I don't think naively evaluating external information would be a wise decision.

So I wondered what an elegant pythonic solution might look like.

+7  A: 
>>> import ast
>>> print ast.literal_eval("(8, 12.25), (13, 15), (16.75, 18.5)")
((8, 12.25), (13, 15), (16.75, 18.5))
nosklo
jfyi, this might not be robust to having a single tuple in the list. What if you input was "(8, 12.25)". That you would get just a tuple instead of a tuple in a tuple. I believe you would get the desired nested tuple if the input was "(8, 12.25)," (note the trailing comma). But I didn't test this as I do not have python 2.6 installed on this machine.
Tom
Good catch Tom. I did not think about that yet and it would actually be a problem in my situation. I am going to check for that after parsing. Thank's for the heads up. Unfortunately the method is not available in python2.5 but In my case that is ok as I am using it in an app engine data import script and not in app engine itself.
tosh
+1  A: 

If you're working with a CSV file, and you want more than the "naive" solution which doesn't handle any errors, you're probably best off using the Python's CSV module.

Edan Maor
Sorry I defined the question a bit vague. The string is actually a value that I get as one of the comma/semicolon separated values. I will remove the CSV bit from the question as it might be confusing. I am using the CSV module by the way. It is great. Thanks for answering though.
tosh
+1  A: 

Download PyParsing.

I've worked with it before. You can get some pretty robust parsing behavior out of it, and I think it provides builtins that will handle your entire parsing needs with this sort of thing. Look up commaSeparatedList and nestedExpr.

inklesspen
+1  A: 
def parse(s):
    tuples = s.split('), ')
    out = []
    for x in tuples:
        a,b = x.strip('()').split(', ')
        out.append((float(a),float(b)))
    return out

this should do the job.

Bartosz Kołodziej
+2  A: 

I've used safe_eval for jobs like this in the past.

Ned Batchelder
+1  A: 

what's wrong with doing it systematically ? split on ")", then go through the list, remove all "(".

>>> s="(8, 12.25), (13, 15), (16.75, 18.5)"
>>> [ i.replace("(","") for i in s.split(")") ]
['8, 12.25', ', 13, 15', ', 16.75, 18.5', '']
>>> b = [ i.replace("(","") for i in s.split(")") ]
>>> for i in b:
...  print i.strip(", ").replace(" ","").split(",")
...
['8', '12.25']
['13', '15']
['16.75', '18.5']
['']

Now you can bring each element into your data structure.