How easy is it to flatten a nested dictionary using yield? In this article, we show that to flatten a multi-layer nested dictionary, use the yield keyword.

Today, we work backwards and restore a flattened dictionary to a nested dictionary.

The target dictionary is:

{
    'a_b_h':1.'a_b_i':2.'a_c_j':3.'a_d':4.'a_c_k':5.'a_e':6
}
Copy the code

We will restore it to:

{
  "a": {
    "b": {
      "h": 1."i": 2
    },
    "c": {
      "j": 3."k": 5
    },
    "d": 4."e": 6}}Copy the code

To implement this requirement, we have two main steps.

Restore each nested dictionary

For {‘a_b_h’:1}, it should actually be restored to:

{'a': {'b': {'h': 1}}}
Copy the code

Now, write a function to unpack, the role of this function is introduced into two parameters [‘ a ‘, ‘b’, ‘h’] and one output {‘ a ‘: {‘ b’ : {‘ h ‘: 1}}} :

def unpack(key, value):
    if len(key) == 1:
        return {key[0]: value}
    else:
        prefix = key.pop(0)
        return {prefix: unpack(key, value)}
Copy the code

Note that the first argument to the unpack function is a list of the form [‘a’, ‘b’, ‘h’]. The running effect is shown in the figure below.

This function uses recursion to take the first argument list item by item as the dictionary key and the remaining items as the sub-dictionary key. When there is only one value left in the list, we are at the very bottom of the list. Use this value as the key of the innermost dictionary and the second parameter as value.

Next, we implement the second function deflat, which divides the target dictionary into key and value pairs and passes the keys to the unpacked function:

def deflat(x):
    for key, value in x.items():
        yield unpack(key.split('_'), value)
Copy the code

In the deflat function, we pass in the target dictionary. Each pair of keys and values in the target dictionary is fetched and passed into an unpack function to construct each small nested dictionary.

The operating effect is shown in the figure below:

Merge the dictionary

Now that we have each of these nested dictionaries, all we have to do is merge them together.

Suppose we have two dictionaries, DST and SRC, and merge the contents of SRC into the DST dictionary in the following cases.

There is no SRC key in DST

Assume that DST = {‘ a ‘: 1}, SRC = {‘ b’ : 1}, so after the merger, DST into {‘ a ‘, 1, ‘b’ : 1}.

The corresponding code is as follows:

def merge(dst, src):
    for key, value in src.items():
        if key not in dst:
            dst[key] = value
Copy the code

DST has SRC keys and values that are dictionaries

Suppose DST = {‘ a ‘: {‘ b’ : 1}}, SRC = {‘ a ‘: {‘ c’ : 1}}, then because of DST and SRC ‘a’ this key, so the problem is converted into a combined {‘ b ‘: 1} and {‘ c’ : 1}, become the first case.

The corresponding code is as follows:

def merge(dst, src):
    for key, value in src.items():
        if key in dst:
            merge(dst[key], value)
Copy the code

DST has a key for SRC and the value is the same

In this case, this is not the case because it would result in the target dictionary having the same key. But dictionaries can’t be repeated.

DST has a key for SRC and the value is of a different type

In this case, the target dictionary has a problem and cannot be merged.

Such as:

{
 'a_b_c': 1
 'a': 2
}
Copy the code

Nested method and does not exist in the dictionary because {‘ a ‘: 3} and {‘ a’ : {‘ b ‘: {‘ c’ : 1}}} only cover each other, cannot be merged.

A complete written

The merge function is written as follows:

def merge(dst, src):
    for key, value in src.items():
        if key not in dst:
            dst[key] = value
        elif isinstance(dst[key], dict) and isinstance(value, dict):
            merge(dst[key], value)
        else:
            raise Exception('Data format is wrong and cannot be converted to nested dictionary')
Copy the code

To solve the problem

Finally, let’s solve this problem by combining the three functions. The operating effect is shown in the figure below:

An error is also normally reported when a target dictionary is passed that cannot be converted