【发布时间】:2016-12-07 06:32:49
【问题描述】:
前言:为了帮助解释为什么我这样做,我将解释最终目标。本质上,我有一个 accounts 列表,它们以非常特定的语法定义。以下是一些示例:
Assets:Bank:Car
Assets:Bank:House
Assets:Savings:Emergency
Assets:Savings:Goals:Roof
Assets:Reserved
如上所示,一个帐户可以有任意数量的父母和子女。最终目标是将上述帐户解析为 Python 中的树结构,该树结构将用于在 Sublime 文本编辑器中提供帐户自动完成功能(即,如果我输入 Assets: 然后查询 auto -完成,我会看到这样的列表:银行,储蓄,保留)
结果:使用前言中的帐户列表,Python 中所需的结果如下所示:
[
{
"Assets":[
{
"Bank":[
"Car",
"House"
]
},
{
"Savings":[
"Emergency",
{
"Goals":[
"Roof"
]
}
]
},
"Reserved"
]
}
]
半解决方案:我能够使用递归将两个基本帐户加在一起。这适用于添加这两个:Assets:Bank:Car 和 Assets:Bank:House。但是,一旦它们开始不同,它就会开始分崩离析并且递归变得混乱,所以我不确定这是否是最好的方法。
import re
def parse_account(account_str):
subs = account_str.split(":")
def separate(subs):
if len(subs) == 1:
return subs
elif len(subs):
return [{subs[0]: separate(subs[1:])}]
return separate(subs)
def merge_dicts(a, b):
# a will be a list with dictionaries and text values and then nested lists/dictionaries/text values
# b will always be a list with ONE dictionary or text value
key = b[0].keys()[0] # this is the dictionary key of the only dictionary in the b list
for item in a: # item is a dictionary or a text value
if isinstance(item, dict): # if item is a dictionary
if key in item:
# Is the value a list with a dict or a list with a text value
if isinstance(b[0][key][0], str):
# Extend the current list with the new value
item[key].extend(b[0][key])
else:
# Recurse to the next child
merge_dicts(item[key], b[0][key])
else:
return a
# Accounts have an "open [name]" syntax for defining them
text = "open Assets:Bank:Car\nopen Assets:Bank:House\nopen Assets:Savings:Emergency\nopen Assets:Savings:Goals:Roof\nopen Assets:Reserved"
EXP = re.compile("open (.*)")
accounts = EXP.findall(text) # This grabs all accounts
# Create a list of all the parsed accounts
dicts = []
for account in accounts:
dicts.append(parse_account(account))
# Attempt to merge two accounts together
final = merge_dicts(dicts[0], dicts[1])
print final
# In the future we would call: reduce(merge_dicts, dicts) to merge all accounts
我可能会以完全错误的方式处理这件事,我会对不同的意见感兴趣。否则,是否有人了解如何使用示例字符串中的剩余帐户进行此操作?
【问题讨论】:
-
你想要的输出会给出一个
SyntaxError(Reserved是一个没有值的键)。 -
抱歉,我将输出粘贴为:
print json.dumps(final),以使其更易于识别。
标签: python dictionary recursion tree nested