Python 将一个字符串解析成n-depth字典
Python parse a string into n-depth dictionary
我有一串由定界符分隔的键 |
后跟一个值。
字符串可能是
key1|key2|key3=value
这应该解析为
dct[key1][key2][key3] = value
个别词典可能已经存在。
为了启动原型,我已经像这样对字典的创建进行了硬编码(字段是主字典 - 已经存在,s 是由 |
(竖线)分隔的键序列:
keys=s.split('|')
if len(keys) == 1:
fields[keys[0]] = field_data
elif len(keys) == 2:
if keys[0] not in fields:
fields[keys[0]] = {}
fields[keys[0]][keys[1]] = field_data
我把它扩展为三层字典,但我知道它很不优雅。
为什么需要三维字典?使用以元组为键的简单字典:
s = "key1|key2|key3=value"
ks, v = s.split("=")
dct = {}
dct[ks] = v
现在您可以像这样访问 dct
:
print(dct[("key1", "key2", "key3")])
输出:
value
例如,
s = "key1|key2|key3=value"
keys, value = s.split('=')
keys = keys.split('|')
base = {}
reduce(
lambda d, k: d.setdefault(k, {}),
keys[:-1],
base
)[keys[-1]] = value
print base # {'key1': {'key2': {'key3': 'value'}}}
如果你经常需要这个,可能值得做一个 class:
class NestedDict(dict):
def __setitem__(self, key, value):
if not isinstance(key, collections.Iterable) or isinstance(key, basestring):
super(NestedDict, self).__setitem__(key, value)
return
keys = list(key)
reduce(
lambda d, k: d.setdefault(k, {}),
keys[:-1],
self
)[keys[-1]] = value
然后:
s = "key1|key2|key3=value"
keys, value = s.split('=')
base = NestedDict()
base[keys.split('|')] = value
print base # {'key1': {'key2': {'key3': 'value'}}}
这将假定您的键和值是字符串。即:
key1|key2|key3=value
dct['key1']['key2']['key3'] = 'value'
# The literal strings
然后您可以创建一个函数,它接受一个字符串并将其拆分。
def str_as_key(string, dictionary=None):
dictionary = dictionary or {}
keys = string.split("|")
keys[-1:] = keys[-1].split("=")
value = keys.pop()
dicti = [dictionary, []]
for key in keys:
dicti = [dicti[0].get(key), dicti[1] + [key]]
if not isinstance(dicti[0], dict):
exec("dictionary['{0}'] = {1}; dicti[0] = {1}".format("']['".join(dicti[1]), '{}'))
exec("dictionary['{}'] = '{}'".format("']['".join(keys), value))
return dictionary
关于此方法的事情是它不必创建新字典。它可以更新一个键并保持其他键不变。例如:
>>> s = "key1|key2|key3=value"
>>> str_as_key(s, {})
{'key1': {'key2': {'key3': 'value'}}}
>>> str_as_key(s, {"key1": {"key2": 12, "foo": "bar"}, "pi": 3.14})
{'pi': 3.14, 'key1': {'foo': 'bar', 'key2': {'key3': 'value'}}}
我有一串由定界符分隔的键 |
后跟一个值。
字符串可能是
key1|key2|key3=value
这应该解析为
dct[key1][key2][key3] = value
个别词典可能已经存在。
为了启动原型,我已经像这样对字典的创建进行了硬编码(字段是主字典 - 已经存在,s 是由 |
(竖线)分隔的键序列:
keys=s.split('|')
if len(keys) == 1:
fields[keys[0]] = field_data
elif len(keys) == 2:
if keys[0] not in fields:
fields[keys[0]] = {}
fields[keys[0]][keys[1]] = field_data
我把它扩展为三层字典,但我知道它很不优雅。
为什么需要三维字典?使用以元组为键的简单字典:
s = "key1|key2|key3=value"
ks, v = s.split("=")
dct = {}
dct[ks] = v
现在您可以像这样访问 dct
:
print(dct[("key1", "key2", "key3")])
输出:
value
例如,
s = "key1|key2|key3=value"
keys, value = s.split('=')
keys = keys.split('|')
base = {}
reduce(
lambda d, k: d.setdefault(k, {}),
keys[:-1],
base
)[keys[-1]] = value
print base # {'key1': {'key2': {'key3': 'value'}}}
如果你经常需要这个,可能值得做一个 class:
class NestedDict(dict):
def __setitem__(self, key, value):
if not isinstance(key, collections.Iterable) or isinstance(key, basestring):
super(NestedDict, self).__setitem__(key, value)
return
keys = list(key)
reduce(
lambda d, k: d.setdefault(k, {}),
keys[:-1],
self
)[keys[-1]] = value
然后:
s = "key1|key2|key3=value"
keys, value = s.split('=')
base = NestedDict()
base[keys.split('|')] = value
print base # {'key1': {'key2': {'key3': 'value'}}}
这将假定您的键和值是字符串。即:
key1|key2|key3=value
dct['key1']['key2']['key3'] = 'value'
# The literal strings
然后您可以创建一个函数,它接受一个字符串并将其拆分。
def str_as_key(string, dictionary=None):
dictionary = dictionary or {}
keys = string.split("|")
keys[-1:] = keys[-1].split("=")
value = keys.pop()
dicti = [dictionary, []]
for key in keys:
dicti = [dicti[0].get(key), dicti[1] + [key]]
if not isinstance(dicti[0], dict):
exec("dictionary['{0}'] = {1}; dicti[0] = {1}".format("']['".join(dicti[1]), '{}'))
exec("dictionary['{}'] = '{}'".format("']['".join(keys), value))
return dictionary
关于此方法的事情是它不必创建新字典。它可以更新一个键并保持其他键不变。例如:
>>> s = "key1|key2|key3=value"
>>> str_as_key(s, {})
{'key1': {'key2': {'key3': 'value'}}}
>>> str_as_key(s, {"key1": {"key2": 12, "foo": "bar"}, "pi": 3.14})
{'pi': 3.14, 'key1': {'foo': 'bar', 'key2': {'key3': 'value'}}}