Python Generate a dynamic dictionary from the list of keys

前端 未结 7 1355
长发绾君心
长发绾君心 2021-02-09 02:38

I do have a list as given below -

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

How can I ge

相关标签:
7条回答
  • 2021-02-09 02:56

    I'm just learning python, so my code could be not very pythonic, but here's my code

    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'}}}}}}
    
    0 讨论(0)
  • 2021-02-09 03:00

    You can do this by making nested 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'
    

    This has the nice advantage of being able to write

    mydict['a']['b'] = 4
    

    without necessarily having to use the setpath helper.

    You can do it without recursive defaultdicts too:

    def setpath(d, p, k):
        if len(p) == 1:
            d[p[0]] = k
        else:
            setpath(d.setdefault(p[0], {}), p[1:], k)
    
    0 讨论(0)
  • 2021-02-09 03:01

    Use tuple(keyList1) as key. (tuples are immutable and therefore can be dict keys).

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

    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.

    0 讨论(0)
  • 2021-02-09 03:03

    Create your own class derived from dict where the init method 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).

    Forget the idea of

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

    as it is confusing with subindexes.

    0 讨论(0)
  • 2021-02-09 03:06
    >>> 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})
    
    0 讨论(0)
  • 2021-02-09 03:06

    Perhaps you could subclass 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'}}}}}}
    
    0 讨论(0)
提交回复
热议问题