如何创建嵌套的字典键并从命名空间键值对列表中为它们分配值?

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_inhere的实现。一个更简单的替代品可能是

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'}