7

I have a string with format:

["('colA':'datA1', 'colB':'datB1', 'colC':'datC1')",
 "('colA':'datA2', 'colB':'datB2', 'colC':'datC2')",
 ..........
 "('colA':'datAn', 'colB':'datBn', 'colC':'datCn')]

And i need to obtain a dict:

[{'colA': 'datA1', 'colB': 'datB1', 'colC': 'datC1'},
 {'colA': 'datA2', 'colB': 'datB2', 'colC': 'datC2'},
 ..........
 {'colA': 'datAn', 'colB': 'datBn', 'colC': 'datCn'}]

If possible I need to do it with Python's own functions or at least without using loops, but I do not know if this is possible.

3
  • 2
    Where does 'jack' come from? That is not in the original data. Nor is Sape. Where do the number 4098 and 4130 come from? From calculations? Commented Nov 26, 2016 at 20:19
  • Sorry, error from the clipboard. Thanks for pointing it out. I edit Commented Nov 26, 2016 at 20:20
  • hehe if it werent for the ( and ) in the string you could run eval() on each string Commented Nov 26, 2016 at 20:21

5 Answers 5

11

Replace the parentheses with curly braces and use ast.literal_eval:

import ast
l = ["('colA':'datA1', 'colB':'datB1', 'colC':'datC1')",
 "('colA':'datA2', 'colB':'datB2', 'colC':'datC2')",
 "('colA':'datAn', 'colB':'datBn', 'colC':'datCn')"]
result = [ast.literal_eval('{%s}' % item[1:-1]) for item in l]

The result:

>>> import pprint
>>> pprint.pprint(result)
[{'colA': 'datA1', 'colB': 'datB1', 'colC': 'datC1'},
 {'colA': 'datA2', 'colB': 'datB2', 'colC': 'datC2'},
 {'colA': 'datAn', 'colB': 'datBn', 'colC': 'datCn'}]
Sign up to request clarification or add additional context in comments.

1 Comment

this is the proper answer - using plain eval like the other suggests can be dangerous. See nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
2

As @nexus66 suggested, here's a more streamlined version of that answer:

l = ["('colA':'datA1', 'colB':'datB1', 'colC':'datC1')",
 "('colA':'datA2', 'colB':'datB2', 'colC':'datC2')",
 "('colA':'datAn', 'colB':'datBn', 'colC':'datCn')"]
result = [dict(
               item.replace("'", '').split(':')
               for item in s[1:-1].split(', ')
               )
          for s in l]

1 Comment

Thank you for the two answers you have given me. I prefer this one for not using an additional module.
2

Avoid using eval(as it's unsafe) function and rely on proper dict structure(in json representation). Use the following approach with re.sub and json.loads functions:

import json, re

d = ["('colA':'datA1', 'colB':'datB1', 'colC':'datC1')",
 "('colA':'datA2', 'colB':'datB2', 'colC':'datC2')",
 "('colA':'datAn', 'colB':'datBn', 'colC':'datCn')"]

try:
    l = [json.loads('{' + re.sub(r'\'', '"', s).strip('()') + '}') for s in d]
    print(l)
except json.decoder.JSONDecodeError as err:
    print('JSONDecodeError: ', err)

The output:

[{'colC': 'datC1', 'colA': 'datA1', 'colB': 'datB1'}, {'colC': 'datC2', 'colA': 'datA2', 'colB': 'datB2'}, {'colC': 'datCn', 'colA': 'datAn', 'colB': 'datBn'}]

2 Comments

What sort of exception is that bare except: supposed to catch?
@TigerhawkT3, it can be bare in some simple cases, but now I've added specific Exception type, see my update. In more strict(real) situations, of course, we can raise Exception('...')
1

My solution to your question without importing any module:

my_input = ["('colA':'datA1', 'colB':'datB1', 'colC':'datC1')",
 "('colA':'datA2', 'colB':'datB2', 'colC':'datC2')",
 "('colA':'datAn', 'colB':'datBn', 'colC':'datCn')"]

global_list =[]
for i in my_input:
    intern_dict = {}
    for j in i.replace("(", "").replace(")", "").split(","):
        c = j.split(":")
        intern_dict["".join(c[0].replace("'", "").strip())] = "".join(c[1].replace("'","").strip())     
    global_list.append(intern_dict)

print("Type of global_list: {0}\n".format(type(global_list)))
print(global_list)
print("\nType of elements inside global_list\n")
for i in global_list:
    print("{0}\tType: {1}".format(i, type(i)))

Output:

Type of global_list: <class 'list'>

[{'colA': 'datA1', 'colC': 'datC1', 'colB': 'datB1'}, {'colA': 'datA2', 'colC': 'datC2', 'colB': 'datB2'}, {'colA': 'datAn', 'colC': 'datCn', 'colB': 'datBn'}]

Type of elements inside global_list

{'colA': 'datA1', 'colC': 'datC1', 'colB': 'datB1'} Type: <class 'dict'>
{'colA': 'datA2', 'colC': 'datC2', 'colB': 'datB2'} Type: <class 'dict'>
{'colA': 'datAn', 'colC': 'datCn', 'colB': 'datBn'} Type: <class 'dict'>

6 Comments

This algorithm has some glaring oddities, such as the unnecessary generator expression with k for k in....
''.join(k for k in iterable) accomplishes the same result as ''.join(iterable).
Yes ! You're right. I edited my answer. Thanks for pointing the oddities.
The entire thing could just be result = [dict(item.replace("'", '').split(':') for item in s[1:-1].split(', ')) for s in my_input].
Awesome ! You should post your solution. It's more pythonic !
|
-3

Use json,

import json

lst = "yourstringhere"

dict = json.load(lst)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.