We often encounter various types of dictionary data, such as:

nest_dict = {
    'a': 1.'b': {
        'c': 2.'d': 3.'e': {'f': 4}},'g': {'h': 5},
    'i': 6.'j': {'k': {'l': {'m': 8}}}}Copy the code

Is there an easy way to squash it into:

{
    'a': 1.'b_c': 2.'b_d': 3.'b_e_f': 4.'g_h': 5.'i': 6.'j_k_l_m': 8
}
Copy the code

You must have thought of recursively solving this problem, so you can try it out and see how many lines of code your recursive function has.

Today, we use the yield keyword to implement this requirement, which requires only eight lines of code without being too flashy. In the showy case, you only need three lines of code.

To squash the nested dictionary quickly, we need to process the fields from below the net. For example, b – > e – > – > 4 f this path, we first put the innermost {‘ f ‘: 4} into a tuple (‘ f’, 4). Then, throw this tuple up, and you get the tuple (‘e’, (‘f’, 4)). We put the e in the front of the joining together to f, become: (‘ e_f, 4), continue to throw up, get (‘ b ‘(‘ e_f, 4)). Splicing b over e_f gives (‘b_e_f’, 4). Complete the assembly of a circuit.

This logic, if implemented using the yield keyword, is:

def flat(x):
    for key, value in x.items():
        if isinstance(value, dict):
            for k, v in flat(value):
                k = f'{key}_{k}'
                yield (k, v)
        else:
            yield (key, value)
Copy the code

The running results are as follows:

By using the yield keyword, dictionary keys are assembled from the inside out, layer by layer, as if on an assembly line, forming a complete path.

In the next article, we will continue to use the yield keyword to solve the case of mixed dictionary and list nesting.