将String转换为多级字典键?

时间:2017-12-11 14:28:21

标签: python dictionary

我让用户能够检查多级字典中的特定键。我的想法是他们会像这样通过密钥路径:

root.subelement1.subelement2.key

这可以是任意长度和深度。

一旦我收到用户的字符串(上图),我就会将其拆分并获取每个组件的列表:

elements = ['root', 'subelement1', 'subelement2', 'key']

所有这一切我都能做到。接下来的部分是我被困住的地方。如何查询上面指定的字典键,当它是任意长度的时候?

我最初的想法是做my_dict[elements[0]][elements[1]]之类的事情......但是当我的用户没有完全按照我期望的长度传递时,这不会缩放或工作。

在这种情况下,如何以任意键深度获取数据?

几个例子:

  • 用户通过country.US.NewYork =>我查询`my_dict [' country'] [' US'] [' NewYork']
  • 用户通过department.accounting =>我查询my_dict['department']['accounting']
  • 用户通过id =>我查询my_dict['id']
  • 用户通过district.District15.HenryBristow.principal =>我查询my_dict['district']['District15']['HenryBristow']['principal']

5 个答案:

答案 0 :(得分:6)

你可以使用reduce来查询嵌套词典中的键:

q = "district.District15.HenryBristow.principal"
my_dict  = {"district" : {"District15" : {"HenryBristow" : {"principal" : 12}}}}

from functools import reduce  # python 3 only

print(reduce(lambda x,y : x[y],q.split("."),my_dict))

结果:

12

如果您想避免捕获KeyError以防此路径中不存在数据,您可以将get与默认值一起用作空字典:

reduce(lambda x,y : x.get(y,{}),q.split("."),my_dict)

尝试获取未知值会返回一个空字典。唯一的缺点是你不知道哪里确切地说路径丢失了,所以也许保留KeyError不会那么糟糕:

try:
    v = reduce(lambda x,y : x[y],q.split("."),my_dict)
except KeyError as e:
    print("Missing key: {} in path {}".format(e,q))
    v = None

答案 1 :(得分:1)

你可以像下面这样做

my_dict = someDict

tmpDict = dict(someDict)   # a coppy of dict
input = "x.u.z"
array = input.split(".")
for key in array:
    tmpDict = tmpDict[key]
print(tmpDict)

但您的问题非常具有挑战性: 如果用户发送 country.us ,请转到my-dict.country.us

但如果my_dict中的某个路径是列表代码,会发生什么情况会导致错误 你可以通过检查类型

来处理这个问题
if isinstance(tmpDict , dict ):
    tmpDict = tmpDict[key]
else:
    # u should say what u want else (a Recursive method u will need)

修改 如果用户地址可能有误,你应该检查my_dict是否有这个字段或者没有示例代码在下面但是如果我不喜欢那么会有很多!     如果key不在tmpDict中:         打印(“坏道”)         返回

答案 2 :(得分:1)

使用递归。例如:

root = {
    'subelement1': {
        'subelement2': {
            'key': 'value'
        }
    }
}

elements = ['subelement1', 'subelement2', 'key']


def getElem(d, keys):
    if keys == []:
        return None
    else:
        key = keys[0]
        remainingKeys = keys[1:]
        if remainingKeys == []:
            return d[key]
        else:
            if type(d[key]) == dict:
                return getElem(d[key], remainingKeys)
            else:
                return None


print(getElem(root, elements))

答案 3 :(得分:0)

从python 2.x的角度来看,你可以用reduce来做到这一点。

symbol_put

但总的来说,如果你想在抛出query_list = keys.split(":") print reduce(lambda x,y: x[y], [my_dict] + query_list) 之外进行错误处理,你会想要用递归或迭代函数来做这件事。

答案 4 :(得分:0)

您可以使用for循环遍历字典:

s = 'root.subelement1.subelement2.key'
d1 = {'root':{'subelement1':{'subelement2':{'key':15, 'key1':18}}}}
new_d = d1
for key in s.split('.'):
    new_d = new_d[key]

print(new_d)

输出:

15