Python从键列表生成动态字典
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17462011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python Generate a dynamic dictionary from the list of keys
提问by Abhishek Kulkarni
I do have a list as given below -
我确实有一个列表,如下所示 -
keyList1 = ["Person", "Male", "Boy", "Student", "id_123", "Name"]
value1 = "Roger"
How can I generate dynamic dictionary which can be retrieved as below -
如何生成可以检索的动态字典,如下所示 -
mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] = value
The list could be anything; Variable Length or consisting of "N" number of elements unknown to me...
列表可以是任何东西;可变长度或由我未知的“N”个元素组成...
Now I do have another list, so that My dictionary should be updated accordingly
现在我有另一个列表,所以我的字典应该相应地更新
keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"]
value2 = 25
i.e. If Keys "Person", "Male", "Boy", "Student", "id_123" already exists, the new key "age" should be appended ...
即如果键“人”、“男”、“男孩”、“学生”、“id_123”已经存在,则应附加新键“年龄”...
采纳答案by Roman Pekar
I'm just learning python, so my code could be not very pythonic, but here's my code
我只是在学习 python,所以我的代码可能不是很 pythonic,但这是我的代码
d = {}
keyList1 = ["Person", "Male", "Boy", "Student", "id_123", "Name"]
keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"]
value1 = "Roger"
value2 = 3
def insert(cur, list, value):
if len(list) == 1:
cur[list[0]] = value
return
if not cur.has_key(list[0]):
cur[list[0]] = {}
insert(cur[list[0]], list[1:], value)
insert(d, keyList1, value1)
insert(d, keyList2, value2)
{'Person': {'Male': {'Boy': {'Student': {'id_123': {'Age': 3, 'Name': 'Roger'}}}}}}
回答by John La Rooy
>>> mydict = {}
>>> keyList1 = ["Person", "Male", "Boy", "Student", "id_123", "Name"]
>>> value1 = "Roger"
>>> reduce(lambda x, y: x.setdefault(y, {}), keyList1, mydict)
{}
>>> mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] = value1
You can also do it in one step like this
你也可以像这样一步一步完成
>>> keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"]
>>> value2 = 25
>>> reduce(lambda x,y: x.setdefault(y,{}), keyList2[:-1], mydict).update({keyList2[-1]: value2})
回答by Steve Barnes
Create your own class derived from dict where the initmethod takes a list and a single value as inputs and iterate through the list setting the keys to value, define an update method that takes a list and a new value and for each item that is not already a key set it to the new value, (assuming that is what you need).
创建您自己的从 dict 派生的类,其中init方法将列表和单个值作为输入,并遍历列表,将键设置为值,定义一个更新方法,该方法采用列表和新值,并为每个不是已经有一个键将其设置为新值,(假设这是您需要的)。
Forget the idea of
忘记这个想法
mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] = value1`
mydict["人"]["男"]["男孩"]["学生"]["id_123"]["姓名"] = value1`
as it is confusing with subindexes.
因为它与子索引混淆。
回答by nneonneo
You can do this by making nested defaultdict
s:
您可以通过嵌套defaultdict
s来做到这一点:
from collections import defaultdict
def recursive_defaultdict():
return defaultdict(recursive_defaultdict)
def setpath(d, p, k):
if len(p) == 1:
d[p[0]] = k
else:
setpath(d[p[0]], p[1:], k)
mydict = recursive_defaultdict()
setpath(mydict, ["Person", "Male", "Boy", "Student", "id_123", "Name"], 'Roger')
print mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"]
# prints 'Roger'
This has the nice advantage of being able to write
这有一个很好的优势,可以写
mydict['a']['b'] = 4
without necessarily having to use the setpath
helper.
不必使用setpath
助手。
You can do it without recursive defaultdict
s too:
您也可以在没有递归defaultdict
的情况下做到这一点:
def setpath(d, p, k):
if len(p) == 1:
d[p[0]] = k
else:
setpath(d.setdefault(p[0], {}), p[1:], k)
回答by Shruti Joshi
I am trying to dealing with similar stuff, so I can suggest some guidelines, but again I am naive in Python, so this is just a guideline...
我正在尝试处理类似的东西,所以我可以提出一些指导方针,但我再次对 Python 感到天真,所以这只是一个指导方针......
you have a list of keys , so you can definitely start with a loop iterating for each value and then assign the value
您有一个键列表,因此您绝对可以从对每个值进行迭代的循环开始,然后分配该值
like
喜欢
for i in keylist:
if type(keylist[i]) == dict:
do something
else:
keylist[i] = {}
in the do something, you need to increment i and change index to [i][i+1] and then follow the same untill i+n = len(keylist)
在做某事时,您需要增加 i 并将索引更改为 [i][i+1] 然后按照相同的操作直到 i+n = len(keylist)
回答by Torben Klein
Use tuple(keyList1)
as key. (tuples are immutable and therefore can be dict keys).
tuple(keyList1)
作为钥匙使用。(元组是不可变的,因此可以是字典键)。
You will have a world of headache with the nested dict approach. (nested loops for enumeration, legacy data when the hierarchy needs to change, etc.).
嵌套 dict 方法会让您头疼。(用于枚举的嵌套循环、层次结构需要更改时的遗留数据等)。
On a second thought, maybe you should define a person class
再想一想,也许你应该定义一个人类
class Person(object):
gender = "Male"
group = "Student"
id = 123
Name = "John Doe"
then use a list of all persons and filter with e.g.
然后使用所有人的列表并使用例如过滤
male_students = [s for s in ALL_PERSONS where s.gender=="Male" and s.group="Student"]
... for <= 10000 students you should be fine performancewise.
...对于 <= 10000 名学生,您应该表现良好。
回答by Rao
Perhaps you could subclass dict:
也许你可以将 dict 子类化:
class ChainDict(dict):
def set_key_chain(self, keyList, value):
t = self
for k in keyList[:-1]:
t = t.setdefault(k, {})
t.setdefault(keyList[-1], value)
c = ChainDict()
c.set_key_chain(['Person', 'Male', 'Boy', 'Student', 'id_123', 'Name'], 'Roger')
print c
>>{'Person': {'Male': {'Boy': {'Student': {'id_123': {'Name': 'Roger'}}}}}}
c.set_key_chain(['Person', 'Male', 'Boy', 'Student', 'id_123', 'Age'], 25)
print c
>>{'Person': {'Male': {'Boy': {'Student': {'id_123': {'Age': 25,
'Name': 'Roger'}}}}}}