pythonpython-3.xlistdictionarysetdefault

Is it possible to have nested dictionary using setdefault, appending to a list?


I would like to have a nested dictionary with a list of values that are attached to the sub-key. Can't get the sub-key to recognise.

month = {}
    for row in date:
        month.setdefault(row[1],{row[0]: []})
        month[row[0]].append(row[4])

print(month[main_key][sub_key])

I expect a list of values to be populated out through the appending method. However, I keep getting a keyError.

The desired output:

{'row[1]': {'row[0]' :[row[4], row[4], row[4]],
            'row[0]' :[row[4], row[4], row[4]]}}

Solution

  • Here's a simple example of what I think you are trying to achieve:

    >>> rows = [[1,2,3], [1,2,4], [1,3,3], [1,3,5], [2,3,9], [2,3,5]]
    >>> ret = {}
    >>> for row in rows:
    ...     ret.setdefault(row[0], {}).setdefault(row[1], []).append(row[2])
    ...
    >>> ret
    {1: {2: [3, 4], 3: [3, 5]}, 2: {3: [9, 5]}}
    

    How does it work? For each row:

    1. We look for row[0] in ret keys. If it is not present, we add the pair (row[0], {}) to the dict, {} being the nested dict. It it is present, we continue.
    2. The value row[1] is the key of the nested dict. We look for it in ret[row[0]] (the first setdefault return): if it is not present, we add an empty list.
    3. We add the value row[2] to the list ret[row[0]][row[1]]

    Remember that:

    ret.setdefault(row[0], value_if_absent).func()
    

    Means:

    if row[0] not in ret:
        ret[row[0]] = value_if_absent
    
    ret[row[0]].func()
    

    Usaully, value_if_absent is a container and func is one of append, extend, update, ... methods. But func may also be a setdefault to create a new container if needed.