Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert tuple-strings to tuple of strings

Tags:

python

My Input is:

input = ['(var1, )', '(var2,var3)']

Expected Output is:

output = [('var1', ), ('var2','var3')]

Iterating over input and using eval/literal_eval on the tuple-strings is not possible:

>>> eval('(var1, )')
>>> NameError: name 'var1' is not defined

How can I convert an item such as '(var1, )' to a tuple where the inner objects are treated as strings instead of variables?

Is there a simpler way than writing a parser or using regex?

like image 768
runDOSrun Avatar asked Feb 02 '16 12:02

runDOSrun


2 Answers

For each occurrence of a variable, eval searches the symbol table for the name of the variable. It's possible to provide a custom mapping that will return the key name for every missing key:

class FakeNamespace(dict):
    def __missing__(self, key):
        return key

Example:

In [38]: eval('(var1,)', FakeNamespace())
Out[38]: ('var1',)

In [39]: eval('(var2, var3)', FakeNamespace())
Out[39]: ('var2', 'var3')

Note: eval copies current globals to the submitted globals dictionary, if it doesn't have __builtins__. That means that the expression will have access to built-in functions, exceptions and constants, as well as variables in your namespace. You can try to solve this by passing FakeNamespace(__builtins__=<None or some other value>) instead of just FakeNamespace(), but it won't make eval 100% safe (Python eval: is it still dangerous if I disable builtins and attribute access?)

like image 159
vaultah Avatar answered Sep 30 '22 10:09

vaultah


Try this:

tuples = [tuple(filter(None, t.strip('()').strip().split(','))) for t in input]

For example:

In [16]: tuples = [tuple(filter(None, t.strip('()').strip().split(','))) for t in input]

In [17]: tuples
Out[17]: [('var1',), ('var2', 'var3')]

We're iterating through our list of tuple strings, and for each one, removing the ()s, then splitting our string into a list by the ,, and then converting our list back into a tuple. We use filter() to remove empty elements.

like image 34
Will Avatar answered Sep 30 '22 10:09

Will