2016-04-26 38 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()] 
相關問題