2016-04-26 83 views
4

拿一本字典获取字典值,其中关键的部分是在一个字符串

dict = {"word":{"a":{"b":2}}} 

我想要得到的值2 要访问这个我能做到这一点dict["word"]["a"]["b"]

不过,我想要知道我可以在一个字符串

有键(["a"]["b]部分)的一部分,是指它像这样

东西0

或类似的东西

我知道这种语法是不正确的,但是有可能做这样的事情吗?

在Python 3.x的

编辑: 一个更好的字典例子可能是这样的

dict = { 
"word":{"a":{"b":2}} 
"hello":{"a":{"b":1}} 
"mouse":{"a":{"b":5}} 
} 

如何获得B的在各种情况下的价值?您可能希望在密钥可能更改的情况下避免在密钥的["a"]["b"]位中进行硬编码。

+2

什么是使用这种背景下? – mattsap

+1

这可能是一个“xy问题”的情况 - 以这种方式通过字符串引用嵌套的字典项目是不可能的,但是您想用这种方式做什么很可能......用另一种方式。那么,你想怎么做呢? – Roberto

+0

Python有一个'eval'函数可能会使它工作 - 但我同意以前的意见。 – usr2564301

回答

3

请勿使用dict作为变量名称,因为它会隐藏内置函数。


其中一种方法是使用re module。这里的主要想法是,你正在利用正则表达式来找出密钥。获得密钥列表后,提取数据是一件容易的事情。

>>> d = {"word":{"a":{"b":2}}} 
>>> s = '["a"]["b"]' 
>>> import re 
>>> keys = re.findall(r'\["(.+?)"\]',s) 
>>> d["word"][keys[0]][keys[1]] 
2 

如果有很多键,那么你可以使用reducefunctools包。

>>> import functools 
>>> functools.reduce(dict.__getitem__, keys, d['word']) 
2 

(如JonClements在comment已经提到)对于较长的类型的字典,你可以使用一个list comprehension

>>> d = { 
... "word":{"a":{"b":2}}, 
... "hello":{"a":{"b":1}}, 
... "mouse":{"a":{"b":5}} 
... } 
>>> [functools.reduce(dict.__getitem__, keys, d[i]) for i in d] 
[2, 5, 1] 

但是请注意,由于字典键的无序性,列表的输出可能不如预期。一个更好的办法是降低整个字典到一个新的(使用字典理解),如

>>> {i:functools.reduce(dict.__getitem__, keys, d[i]) for i in d} 
{'word': 2, 'mouse': 5, 'hello': 1} 
+0

当然 - 一旦你提取了键(以任何语法),你就可以调整:'functools.reduce(dict .__ getitem__,'ab',d ['word']) '让这个更灵活...只需要用一个很好的语法来获取''ab''(甚至可以从'input''上运行'ast.literal_eval'就可以了......) –

+0

可能想要使如果存在多字符/非字符串键,则可以使用键/列表/元组来代替字符串(即:保留原始的're.findall'' keys')。 –

+0

当然 - 当使用list-comp时值的顺序(假设)它们很重要可能会令人惊讶 - 除非源代码是OrderedDict :) –

2

最好的办法是写自己的语法,您会解析。你必须使用一个永远不会出现在密钥中的charachter,一个流行的例子是.,但相似,$,|也适用。

def get(d, key): 
    kp = key.split('.') 
    for k in kp: 
     d = d[k] 
    return d 

d = {'a': {'b': 2}} 
get(d, 'a.b') 
>>> 2 

编辑更新的问题:

所以你要能得到特别是在每个这种情况下A·B的值的列表?如果是的话,你仍然可以使用上面,像这样

d = { 
"word":{"a":{"b":2}}, 
"hello":{"a":{"b":1}}, 
"mouse":{"a":{"b":5}}, 
} 

# nesting calls to get just to show it is flexible like that 
[get(get(d, k), 'a.b') for k in d.keys()] 
# if you wanted to generate a dict of {"word": val} it would look like this 
{k:get(get(d, k), 'a.b') for k in d.keys()} 

它甚至工作方法,如果你的可变部分是在中间

d = { 
"x": {"word":{"a":{"b":2}}}, 
"x": {"hello":{"a":{"b":1}}}, 
"x": {"mouse":{"a":{"b":5}}}, 
} 

# using more calls to get just to show it is flexible like that 
[get(get(d, 'x.'+k), 'a.b') for k in get(d, 'x').keys()] 
相关问题