2

I am trying to parse a string to separate the lists within the string. I currently have the string:

string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"

Is there any way to parse string so that the dictionary key is the first element of the list and the value of the key is the next to elements. For example:

{'q1': ('0','q1'), 'q1': ('1','q2'), 'q2': ('0','q2'), 'q2': ('1', 'q1')}
  • 5
    you can't have duplicate elements in dictionary as keys. q1 and q2 are repeated twice in your expected output, you can't have this. – venpa Dec 04 '14 at 08:25
  • unless you change the behaviour of a Python dictionnary by redefining a class but I guess that's not the purpose :) – Colonel Beauvel Dec 04 '14 at 08:28
  • is there a way to add another value to an existing key in a dictionary? – user3246978 Dec 04 '14 at 08:29
  • yes, you could have like:`{'q1': [('0','q1'), ('1','q2')], 'q2': [('0','q2'), ('1', 'q1')]}`. is this you want? – venpa Dec 04 '14 at 08:40

5 Answers5

4

Insted of dictionary you can have list:
you can use ast.literal_eval to parse python data structure from string

>>> import ast
>>> my_string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
>>> k = ast.literal_eval(my_string)
>>> k
[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]
>>> [[x[0],tuple(x[1:])] for x in k]
[['q1', ('0', 'q1')], ['q1', ('1', 'q2')], ['q2', ('0', 'q2')], ['q2', ('1', 'q1')]]
Hackaholic
  • 19,069
  • 5
  • 54
  • 72
3

You can use JSON but the string format has to be a dict and you cannot have 2 times the same key:

import json

string ='{"q": ["0", "q1"], "q1": ["1", "q2"], "q3": ["1", "q1"], "q2": ["0", "q2"]}'

dict = json.loads(string)

print dict
Output: {'q': ['0', 'q1'], 'q1': ['1', 'q2'], 'q3': ['1', 'q1'], 'q2': ['0', 'q2']}
AlvaroAV
  • 10,335
  • 12
  • 60
  • 91
3

To keep the duplicates and conform the input format:

import collections
import json
string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
d = collections.defaultdict(list)
for (k, v1, v2) in json.loads(string.replace("'",'"')):
    d[k].append((v1, v2))

With eval (if you trust your input):

import collections
string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
d = collections.defaultdict(list)
for (k, v1, v2) in eval(string):
    d[k].append((v1, v2))

Contents of d:

defaultdict(<type 'list'>, {
    'q1': [('0', 'q1'), ('1', 'q2')],
    'q2': [('0', 'q2'), ('1', 'q1')]
})

EDIT: and with no library at all.

string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
d = {}
for (k, v1, v2) in eval(string):
    d.setdefault(k, []).append((v1, v2))

I'm unable to make it a one-liner though :-)

Aristide
  • 3,606
  • 2
  • 30
  • 50
2

try this

>>> import ast
>>> ast.literal_eval(string)
[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]
>>> list=ast.literal_eval(string)
>>> d={}
>>> for l in list:
...     d[l[0]]=tuple(l[1:])
>>> d
{'q1': ('1', 'q2'), 'q2': ('1', 'q1')}

key is always unique in dict thats why in result showing updated key value pair

Avinash Garg
  • 1,374
  • 14
  • 18
2

You could get nested dictionaries from your string (a little less straightforward than the previous answers). Thanks to Alex Martelli for his answer to Update value of a nested dictionary of varying depth

import ast

def update(d, u):
    for k, v in u.iteritems():
        if isinstance(v, dict):
            r = update(d.get(k, {}), v)
            d[k] = r
        else:
            d[k] = u[k]
    return d

def listToDict(l):
    temp = l[-1]
    for value in l[-2::-1]:
        temp = {value: temp}
    return temp

input = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"

res = {}
for l in ast.literal_eval(input):
    update(res ,listToDict(l))
print res

Output:

{'q1': {'1': 'q2', '0': 'q1'}, 'q2': {'1': 'q1', '0': 'q2'}}
Community
  • 1
  • 1