【问题标题】:Python Generate a dynamic dictionary from the list of keysPython从键列表生成动态字典
【发布时间】:2013-07-04 04:44:14
【问题描述】:

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

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

【问题讨论】:

标签: python dictionary


【解决方案1】:

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

【讨论】:

  • 这最终与我的解决方案非常相似。一个简单的建议:尽可能避免.has_key;更喜欢更快更容易理解的if list[0] not in cur
  • 谢谢,我同意它更具可读性和可读性,但为什么它更快?
  • 尝试使用timeit。在我的电脑上,in 的速度是.has_key 的两倍(0.0672µs 对 0.117µs)。 .has_key 是一个方法查找,而 in 是一个内置函数,它的调度速度要快得多。
  • .has_key 已弃用,在 Python3 中不存在
【解决方案2】:

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

【讨论】:

    【解决方案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'}}}}}}
    

    【讨论】:

      【解决方案4】:

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

      别想了

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

      因为它与子索引混淆。

      【讨论】:

        【解决方案5】:

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

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

        喜欢

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

        在做某事时,您需要增加 i 并将索引更改为 [i][i+1] ,然后按照相同的方式进行操作,直到 i+n = len(keylist)

        【讨论】:

          【解决方案6】:

          使用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"]
          

          ...对于

          【讨论】:

            【解决方案7】:
            >>> 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})
            

            【讨论】:

            • >>> mydict {'Person': {'Male': {'Boy': {'Student': {'id_123': {'Name': 'Roger'}}}}} }
            • @AbhishekKulkarni,呃..reduce(lambda x, y: x.setdefault(y, {}), keyList1, mydict) 在哪里取决于元素的数量或特定的键?
            猜你喜欢
            • 1970-01-01
            • 2011-03-25
            • 2020-01-28
            • 2021-01-23
            • 2019-05-09
            • 2014-05-17
            • 1970-01-01
            • 1970-01-01
            • 2021-10-31
            相关资源
            最近更新 更多