将字典的字符串表示形式转换为字典

Convert string representation of dictionary to dictionary

他们是一种将说明字典的字符串转换为 Python 中的某些字典的方法吗?

例如我想转换字符串:

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')]}"

进入以下形式的字典:

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")']}

我试过 json.loads(s),但不幸的是它需要一些字符串,该字符串已经在字典本身的值处带有引号。

我希望有一些类似的解决方案可以解决这个问题。

备注:像 s 这样的字符串是我从一些 Prolog 字典中生成的。

你可以使用我写的库,叫做 tocode 阅读文档和示例 here:

  1. 安装使用:
pip install tocode==0.1.3
  1. 导入并使用它:
import tocode

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

输出:

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

此代码可能对您有所帮助。

最后,经过长时间使用我的小脑袋,我使用纯 python 而不使用任何模块得到了与您想要的相同的输出。

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)


输出

{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'"]}

这是一种适用于您的示例的方法,但如果嵌套更多或其他原因,则会失败。在这种情况下,我宁愿建议尝试以更易于管理的格式获取数据,例如 JSON,而不是尝试编写一个可以在任何可能情况下工作的解析器。

这是一种通过正则表达式拆分字符串来解析字符串的相当粗略的方法:

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)

输出:

{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')"]}