8

我确实有一个清单,如下所示 -

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

即如果键“Person”、“Male”、“Boy”、“Student”、“id_123”已经存在,则应附加新键“age”...

4

7 回答 7

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'}}}}}}
于 2013-07-04T04:55:32.910 回答
4

您可以通过嵌套defaultdicts 来做到这一点:

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助手。

您也可以在没有递归defaultdicts 的情况下做到这一点:

def setpath(d, p, k):
    if len(p) == 1:
        d[p[0]] = k
    else:
        setpath(d.setdefault(p[0], {}), p[1:], k)
于 2013-07-04T05:18:47.390 回答
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'}}}}}}
于 2013-07-04T05:50:16.660 回答
1

创建您自己的从 dict 派生的类,其中init方法将列表和单个值作为输入,并遍历列表,将键设置为值,定义一个更新方法,该方法采用列表和新值,并为每个不是的项目已经有一个键将其设置为新值(假设这是您需要的)。

忘记这个想法

mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] = value1`

因为它与子索引混淆。

于 2013-07-04T05:09:58.813 回答
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 名学生,您的表现应该很好。

于 2013-07-04T05:35:37.140 回答
0

我正在尝试处理类似的东西,所以我可以提出一些指导方针,但我对 Python 还是很幼稚,所以这只是一个指导方针......

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

喜欢

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

在做某事时,您需要增加 i 并将索引更改为 [i][i+1] 然后遵循相同的直到 i+n = len(keylist)

于 2013-07-04T05:20:28.560 回答
-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})
于 2013-07-04T04:54:32.507 回答