Home > Enterprise >  Convert string representation of dictionary to dictionary
Convert string representation of dictionary to dictionary

Time:04-18

Is their a way to convert strings illustrating dictionaries into some dictionary in Python.

E.g. I want to convert the string:

s = "{1:p→q,2: ¬q,3: ¬ (¬p),4: ¬p,5:[edge(¬p,¬p∧ ¬ (¬p)),edge(¬ (¬p),¬p∧ ¬ (¬p)),rule('∧I')],6:[edge(¬p,p),edge(¬p∧ ¬ (¬p),p),rule('¬E')],7:[edge(p,q),edge(p→q,q),rule('→E')],8:[edge(q,q∧ ¬q),edge(¬q,q∧ ¬q),rule('∧I')],9:[edge(¬ (¬p),¬p),edge(q∧ ¬q,¬p),rule('¬E')]}"

into some dictionary of following form:

d = {1:'p→q',2: '¬q',3: '¬ (¬p)',4: '¬p',5:['edge(¬p,¬p∧ ¬ (¬p))','edge(¬ (¬p),¬p∧ ¬ (¬p))','rule("∧I")'],6:['edge(¬p,p)','edge(¬p∧ ¬ (¬p),p)','rule("¬E")'],7:['edge(p,q)','edge(p→q,q)','rule("→E")'],8:['edge(q,q∧ ¬q)','edge(¬q,q∧ ¬q)','rule("∧I")'],9:['edge(¬ (¬p),¬p)','edge(q∧ ¬q,¬p)','rule("¬E")']}

I've tried json.loads(s), but unfortunately it needs some string which already has the quotation marks at the values of the dictionary itself.

I hope some similar solution is possible to solve that problem.

Remark: Strings like s I generate from some Prolog dictionary.

CodePudding user response:

Here is a way to do it that works on your example, but would fail if things were more nested or whatever. In this case, I would rather recommend trying to get the data in a more manageable format, like JSON, rather than try to write a parser that would work in any possible case.

It's a rather crude way of parsing the string by splitting it with regex:

s = "{1:p→q,2: ¬q,3: ¬ (¬p),4: ¬p,5:[edge(¬p,¬p∧ ¬ (¬p)),edge(¬ (¬p),¬p∧ ¬ (¬p)),rule('∧I')],6:[edge(¬p,p),edge(¬p∧ ¬ (¬p),p),rule('¬E')],7:[edge(p,q),edge(p→q,q),rule('→E')],8:[edge(q,q∧ ¬q),edge(¬q,q∧ ¬q),rule('∧I')],9:[edge(¬ (¬p),¬p),edge(q∧ ¬q,¬p),rule('¬E')]}"

import re

# We split on optional ",", a number and ":" 
split = re.split(r',?(\d ):', s[1:-1])
# ['', '1', 'p→q', '2', ' ¬q', '3', ' ¬ (¬p)' ...]

# Convert the numbers to int
split[1::2] = [int(n) for n in split[1::2]]

# We create a dict with the numbers as keys
d = dict(zip(split[1::2], split[2::2]))

# The values starting with "[" need to be converted to lists
for k, v in d.items():
    if v.startswith('['):
        # We split on "edge" or "rule"
        split = re.split(',?(edge|rule)',v[1:-1])
        # and create the list, joining each separator with what follows it
        d[k] = list(''.join(parts) for parts in zip(split[1::2], split[2::2]))
        
print(d)

Output:

{1: 'p→q',
 2: ' ¬q',
 3: ' ¬ (¬p)',
 4: ' ¬p',
 5: ['edge(¬p,¬p∧ ¬ (¬p))', 'edge(¬ (¬p),¬p∧ ¬ (¬p))', "rule('∧I')"],
 6: ['edge(¬p,p)', 'edge(¬p∧ ¬ (¬p),p)', "rule('¬E')"],
 7: ['edge(p,q)', 'edge(p→q,q)', "rule('→E')"],
 8: ['edge(q,q∧ ¬q)', 'edge(¬q,q∧ ¬q)', "rule('∧I')"],
 9: ['edge(¬ (¬p),¬p)', 'edge(q∧ ¬q,¬p)', "rule('¬E')"]}

CodePudding user response:

You can use a library I wrote, called tocode read the doc and example here:

  1. Install it using:
pip install tocode==0.1.3
  1. Import it and use it:
import tocode

# Example
s = "{this: 5, (Alex, Daniel): are good boys, (5, 4): 8.5}"
s = tocode.literal_eval(s, no_string_quotation=True)

Output:

{'this': 5, ('Alex', 'Daniel'): 'are good boys', (5, 4): 8.5}

CodePudding user response:

This code may help you.

Finally, After a long time using my small brain I got the same output as you want using pure python without using any module.

s = "{1:p→q,2: ¬q,3: ¬ (¬p),4: ¬p,5:[edge(¬p,¬p∧ ¬ (¬p)),edge(¬ (¬p),¬p∧ ¬ (¬p)),rule('∧I')],6:[edge(¬p,p),edge(¬p∧ ¬ (¬p),p),rule('¬E')],7:[edge(p,q),edge(p→q,q),rule('→E')],8:[edge(q,q∧ ¬q),edge(¬q,q∧ ¬q),rule('∧I')],9:[edge(¬ (¬p),¬p),edge(q∧ ¬q,¬p),rule('¬E')]}"

s = s[1:-1].split(':')

d = {}
def return_value(value):
    
    if value.startswith('['):
        l = value
        l = l[1:-1].split('),')
        for i in range(len(l)-1):
            l[i] = l[i] ')'
        value = l
    return value
for v in range(len(s)):
   if v != len(s)-2:
        try:
            value = s[v 1][:-2]
            value = return_value(value)
            d[int(s[v][-1])]=value
        except:
            pass

   else:
        value = s[v 1]
        value = return_value(value)
        value[0]=value[0] value[1]
        del value[1]
        d[int(s[v][-1])]=value
print(d)


Output

{1: 'p→q', 2: ' ¬q', 3: ' ¬ (¬p)', 4: ' ¬p', 5: ['edge(¬p,¬p∧ ¬ (¬p))', 'edge(¬ (¬p)', '¬p∧ ¬ (¬p))', "rule('∧I')"], 6: ['edge(¬p,p)', 'edge(¬p∧ ¬ (¬p)', 'p)', "rule('¬E')"], 7: ['edge(p,q)', 'edge(p→q,q)', "rule('→E')"], 8: ['edge(q,q∧ ¬q)', 'edge(¬q,q∧ ¬q)', "rule('∧I')"], 9: ['edge(¬ (¬p)¬p)', 'edge(q∧ ¬q,¬p)', "rule('¬E'"]}
  • Related