String containing list and other data types to dictionary without changing the data type in python

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



String containing list and other data types to dictionary without changing the data type in python



I have one string as below:


key_val = "count=2, name=['hello', 'hi'], word='Dial::100', roll=12"



I need to get the dictionary from the string as below:


d_key_val = 'count'=2, 'name'=['hello', 'hi'], 'word'='Dial::100', 'roll'=12



I tried with the following:


regx = r'(?P<key>w+)=(?P<value>[.+?]|d+|S+)'
r_key_val = re_findall(regx, key_val)
for key, value in r_key_val:
d_key_val[key] = value



But it is storing values as all string:


d_key_val = 'count'='2', 'name'="['hello', 'hi']", 'word'="'Dial::100'", 'roll'='12'



Is there any way or regex to store the values as same data type as it has in string?





Related: Simple way to convert a string to a dictionary
– jpp
Aug 8 at 15:05




2 Answers
2



If you are 100% sure that the data is "safe", you could eval it as the parameters to dict:


eval


dict


>>> key_val = "count=2, name=['hello', 'hi'], word='Dial::100', roll=12"
>>> eval("dict(%s)" % key_val)
'count': 2, 'name': ['hello', 'hi'], 'roll': 12, 'word': 'Dial::100'



If you are not sure, better don't use eval, though.


eval



Alternatively, you could use your regex and use ast.literal_eval to evaluate the value:


ast.literal_eval


value


>>> regx = r'(?P<key>w+)=(?P<value>[.+?]|d+|S+)'
>>> k: ast.literal_eval(v) for k, v in re.findall(regx, key_val)
'count': 2, 'name': ['hello', 'hi'], 'roll': 12, 'word': ('Dial::100',)



(Note: I did not check your regex in detail.) You could also try to apply ast.literal_eval to the entire expression, instead of the less safe eval, but this would require some preprocessing, e.g. replacing = with : and adding quotes to the keys, that might not work well with e.g. string values containing those symbols.


ast.literal_eval


eval


=


:



regex cannot do that, but you can! You can write a function like the following that takes the values regex writes out and converts them to the appropriate type.


regex


values


regex


def type_converter(v):
if v[0] == '[' and v[-1] == ']':
v = v.replace('[', '').replace(']', '')
return [type_converter(x) for x in v.split(',')]
try:
v = int(v)
except ValueError:
try:
v = float(v)
except ValueError:
pass
finally:
return v



To add this to your code, simply do:


regx = r'(?P<key>w+)=(?P<value>[.+?]|d+|S+)'
r_key_val = re_findall(regx, key_val)
for key, value in r_key_val:
d_key_val[key] = type_converter(value) # <- this



Example:


lst = ['2', '1.2' ,'foo', '[1, 2]']
print([type(type_converter(x)) for x in lst ])
# [<class 'int'>, <class 'float'>, <class 'str'>, <class 'list'>]



Note that the order in which the try-blocks are written is very important since float('1') does not raise any Errors but the correct type is int!


try


float('1')


int





More difficult for the list part, though. Maybe use ast.literal_eval instead?
– tobias_k
Aug 8 at 11:20


list


ast.literal_eval





@tobias_k I noticed that later but I updated the fuction to a recursive one to handle that. At the end of the day, ast.literal_eval or some fancy json command might be much handier.
– Ev. Kounis
Aug 8 at 11:26



ast.literal_eval


json






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

Creating a leaderboard in HTML/JS