Python从密钥列表生成动态字典

时间:2013-07-04 04:44:14

标签: python dictionary

我确实有一个列表,如下所示 -

keyList1 = ["Person", "Male", "Boy", "Student", "id_123", "Name"]
value1 = "Roger"

如何生成可以检索的动态字典 -

mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] = value

列表可以是任何内容;可变长度或由“N”个未知的元素组成......

现在我有另一个列表,因此我的字典应该相应更新

keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"]
value2 = 25

即。如果密钥“人”,“男”,“男孩”,“学生”,“id_123”已经存在,则应附加新的密钥“年龄”......

7 个答案:

答案 0 :(得分:8)

我只是在学习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'}}}}}}

答案 1 :(得分:4)

您可以通过嵌套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'

这具有能够写

的好处
mydict['a']['b'] = 4

无需使用setpath帮助程序。

你可以在没有递归defaultdict的情况下做到这一点:

def setpath(d, p, k):
    if len(p) == 1:
        d[p[0]] = k
    else:
        setpath(d.setdefault(p[0], {}), p[1:], k)

答案 2 :(得分:3)

也许你可以继承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'}}}}}}

答案 3 :(得分:1)

创建自己的派生自dict的类,其中 init 方法将列表和单个值作为输入并迭代列表设置键值,定义一个列表的更新方法和一个新值,对于每个尚未成为键的项目,将其设置为新值,(假设这是您所需要的)。

忘记

的想法
  
    
      

mydict [“Person”] [“男性”] [“男孩”] [“学生”] [“id_123”] [“姓名”] = value1`

    
  

因为它与子指数混淆。

答案 4 :(得分:0)

我正在尝试处理类似的事情,所以我可以提出一些指导方针,但我再次在Python中很天真,所以这只是一个指导原则......

你有一个按键列表 ,所以你绝对可以从为每个值迭代循环开始,然后分配值

for i in keylist:
if type(keylist[i]) == dict:
        do something
    else:
        keylist[i] = {}

在做某事时,你需要增加i并将索引更改为[i] [i + 1]然后按照相同的直到i + n = len(密钥列表)

答案 5 :(得分:0)

使用tuple(keyList1)作为密钥。 (元组是不可变的,因此可以是字典键)。

使用嵌套式dict方法会让您感到头疼。 (用于枚举的嵌套循环,层次结构需要更改时的遗留数据等)。

再想一想,也许你应该定义一个人类

class Person(object):
    gender = "Male"
    group = "Student"
    id = 123
    Name = "John Doe"

然后使用所有人的列表并过滤例如。

male_students = [s for s in  ALL_PERSONS where s.gender=="Male" and s.group="Student"]

...对于< = 10000名学生,你应该表现得很好。

答案 6 :(得分:-2)

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

您也可以像这样一步完成

>>> keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"]
>>> value2 = 25
>>> reduce(lambda x,y: x.setdefault(y,{}), keyList2[:-1], mydict).update({keyList2[-1]: value2})