如何创建嵌套的字典键并从命名空间键值对列表中为它们分配值?
how can I create nested dictionary keys and assign them values from a list of namespaced key value pairs?
我有如下所示的环境变量:
CONFIG-SOMEKEY-SOMEOTHERKEY = val345
CONFIG-SOMEKEY-SOMEOTHEROTHERKEY = val678
CONFIG-ANOTHERKEY = val222
我想用它们创建一个字典,看起来像:
{
'SOMEKEY': {
'SOMEOTHERKEY': 'val3242',
'SOMEOTHEROTHERKEY': 'val678'
}
'ANOTHERKEY': 'val222'
}
"CONFIG-" 是一个前缀,表示应该使用哪些变量来完成 - 所以我可以像这样轻松地过滤它们:
config_fields = [i for i in os.environ if i.startswith("CONFIG-")]
但我不确定如何遍历字符串、拆分“-”并构建字典。
循环时我在想我可以检查它是否是最后一项并分配值但是它怎么知道它所在的键的完整路径?
我怀疑这是递归的工作我现在才确定如何实现它
您可以使用 toolz 中的 assoc_in
函数。在 -
上拆分名称并切掉前缀。
import os
from toolz.dictoolz import assoc_in
CONFIG={}
for k, v in os.environ.items():
if k.startswith("CONFIG-"):
assoc_in(CONFIG, k.split('-')[1:], v)
如果不想加依赖,可以看assoc_in
here的实现。一个更简单的替代品可能是
def assoc_in(d, ks, v):
for k in ks[:-1]:
d = d.setdefault(k, {})
d[ks[-1]] = v
这里使用.setdefault()
方法获取嵌套的dicts,如果不存在则添加一个新的。
你可以这样做:
data = ['CONFIG-SOMEKEY-SOMEOTHERKEY = val345',
'CONFIG-SOMEKEY-SOMEOTHEROTHERKEY = val678',
'CONFIG-ANOTHERKEY = val222']
result = {}
for e in data:
key, value = e.split(" = ") # split into key and value
path = key.split("-") # split the key into parts
ref = result
for part in path[1:-1]:
ref[part] = part in ref and ref[part] or {}
ref = ref[part]
ref[path[-1]] = value # take the last part of key and set the value
print(result)
输出
{'SOMEKEY': {'SOMEOTHERKEY': 'val345', 'SOMEOTHEROTHERKEY': 'val678'}, 'ANOTHERKEY': 'val222'}
这部分:
ref = result
for part in path[1:-1]:
ref[part] = part in ref and ref[part] or {}
ref = ref[part]
ref[path[-1]] = value
将创建嵌套字典,相当于:
for part in path[1:-1]:
if part not in ref:
ref[part] = {}
ref = ref[part]
因此,如果 part
在字典中,则将 ref 设置为对应于 part
的值,否则创建一个新字典。
您可以像这样获取您的环境变量:
import os
text = [f"{k} = {v}" for k,v in os.environ.items() if k.startswith("CONFIG-")]
print(env)
(灵感来自 How to access environment variable values? - especially this answer)
然后你可以使用字典迭代地拆分你的值:
text = """CONFIG-SOMEKEY-SOMEOTHERKEY = val345
CONFIG-SOMEKEY-SOMEOTHEROTHERKEY = val678
CONFIG-ANOTHERKEY = val222"""
text = text.split("\n")
d = {}
curr_d = d
for part in text:
while "-" in part:
a, b = part.split("-",1)
if '-' in b:
curr_d [a] = curr_d.get(a,{})
curr_d = curr_d[a]
part = b
a, b = part.split("=",1)
curr_d[a] = b
curr_d = d
print(d)
输出:
{'CONFIG': {'SOMEOTHERKEY ': ' val345',
'SOMEOTHEROTHERKEY ': ' val678'},
'ANOTHERKEY ': ' val222'}
我有如下所示的环境变量:
CONFIG-SOMEKEY-SOMEOTHERKEY = val345
CONFIG-SOMEKEY-SOMEOTHEROTHERKEY = val678
CONFIG-ANOTHERKEY = val222
我想用它们创建一个字典,看起来像:
{
'SOMEKEY': {
'SOMEOTHERKEY': 'val3242',
'SOMEOTHEROTHERKEY': 'val678'
}
'ANOTHERKEY': 'val222'
}
"CONFIG-" 是一个前缀,表示应该使用哪些变量来完成 - 所以我可以像这样轻松地过滤它们:
config_fields = [i for i in os.environ if i.startswith("CONFIG-")]
但我不确定如何遍历字符串、拆分“-”并构建字典。
循环时我在想我可以检查它是否是最后一项并分配值但是它怎么知道它所在的键的完整路径?
我怀疑这是递归的工作我现在才确定如何实现它
您可以使用 toolz 中的 assoc_in
函数。在 -
上拆分名称并切掉前缀。
import os
from toolz.dictoolz import assoc_in
CONFIG={}
for k, v in os.environ.items():
if k.startswith("CONFIG-"):
assoc_in(CONFIG, k.split('-')[1:], v)
如果不想加依赖,可以看assoc_in
here的实现。一个更简单的替代品可能是
def assoc_in(d, ks, v):
for k in ks[:-1]:
d = d.setdefault(k, {})
d[ks[-1]] = v
这里使用.setdefault()
方法获取嵌套的dicts,如果不存在则添加一个新的。
你可以这样做:
data = ['CONFIG-SOMEKEY-SOMEOTHERKEY = val345',
'CONFIG-SOMEKEY-SOMEOTHEROTHERKEY = val678',
'CONFIG-ANOTHERKEY = val222']
result = {}
for e in data:
key, value = e.split(" = ") # split into key and value
path = key.split("-") # split the key into parts
ref = result
for part in path[1:-1]:
ref[part] = part in ref and ref[part] or {}
ref = ref[part]
ref[path[-1]] = value # take the last part of key and set the value
print(result)
输出
{'SOMEKEY': {'SOMEOTHERKEY': 'val345', 'SOMEOTHEROTHERKEY': 'val678'}, 'ANOTHERKEY': 'val222'}
这部分:
ref = result
for part in path[1:-1]:
ref[part] = part in ref and ref[part] or {}
ref = ref[part]
ref[path[-1]] = value
将创建嵌套字典,相当于:
for part in path[1:-1]:
if part not in ref:
ref[part] = {}
ref = ref[part]
因此,如果 part
在字典中,则将 ref 设置为对应于 part
的值,否则创建一个新字典。
您可以像这样获取您的环境变量:
import os
text = [f"{k} = {v}" for k,v in os.environ.items() if k.startswith("CONFIG-")]
print(env)
(灵感来自 How to access environment variable values? - especially this answer)
然后你可以使用字典迭代地拆分你的值:
text = """CONFIG-SOMEKEY-SOMEOTHERKEY = val345
CONFIG-SOMEKEY-SOMEOTHEROTHERKEY = val678
CONFIG-ANOTHERKEY = val222"""
text = text.split("\n")
d = {}
curr_d = d
for part in text:
while "-" in part:
a, b = part.split("-",1)
if '-' in b:
curr_d [a] = curr_d.get(a,{})
curr_d = curr_d[a]
part = b
a, b = part.split("=",1)
curr_d[a] = b
curr_d = d
print(d)
输出:
{'CONFIG': {'SOMEOTHERKEY ': ' val345',
'SOMEOTHEROTHERKEY ': ' val678'},
'ANOTHERKEY ': ' val222'}