Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Nevermind. As indicated by juanpa.arrivillaga, list comprehension does not return a dictionary ><

Context

I have the following python code (see next piece of code). I would like to try and optimize it to compare the execution time between regular loop and list comprehension.

Regular loop version

def flatten_json( nested_dict, flattened_dict={}, superior_level_key: str = ""):

    for key, value in nested_dict.items():
        if type(nested_dict[key]) is dict:
            flattened_dict = flatten_json(
                nested_dict[key], flattened_dict, "{}_".format(key))
        else:
            flattened_dict['{}{}'.format(superior_level_key, key)] = value

    return flattened_dict


import json

with open('json.json') as j:
    d = json.load(j)
    print(flatten_json(d, {}, ""))

Current, failing, list comprehension version

def flatten_json(nested_dict, flattened_dict={}, superior_level_key: str = ""):

    return [flatten_json(nested_dict[key], flattened_dict, "{}_".format(key))
            if type(nested_dict) is dict
            else value for key, value in nested_dict.items()]


import json

with open('json.json') as j:
    d = json.load(j)
    print(flatten_json(d, {}, ""))

Error

The list comprehension version throws the following error:

Traceback (most recent call last):
  File "p1.py", line 13, in <module>
    print(flatten_json(d, {}, ""))
  File "p1.py", line 3, in flatten_json
    return [flatten_json(nested_dict[key], flattened_dict, "{}_".format(key))
  File "p1.py", line 3, in <listcomp>
    return [flatten_json(nested_dict[key], flattened_dict, "{}_".format(key))
  File "p1.py", line 5, in flatten_json
    else value for key, value in nested_dict.items()]
AttributeError: 'float' object has no attribute 'items'

Question

Why is it throwing that error and how to fix it ?

Input

{
    "_score": 1.0,
    "_index": "sirene_prod",
    "_id": "AXSp612eur2DngRir4BH",
    "_type": "sirene_prod",
    "_source": {
        "enseigne": "",
        "codpos": {
            "cp": "17300",
            "bur_distrib": "300",
            "depet": "17"
        },
        "id": "ddf9e5b2aa0099ff6934a3d83b1678f64e27859e377362ef8682a9b1",
        "l3_normalisee": "",
        "apet700": "10.71C",
        "sigle": "",
        "siren": "793120569",
        "libapen": "Boulangerie et boulangerie-patisserie",
        "apen700": "10.71C",
        "cedex": "",
        "typvoie": "AV",
        "numvoie": 33,
        "nom": "",
        "depet_limit": [
            "16",
            "24",
            "33",
            "79",
            "85"
        ],
        "libcom": "ROCHEFORT",
        "l2_normalisee": {
            "text": "",
            "nom": "",
            "initial": ""
        },
        "libvoie": "GAMBETTA",
        "nic": "00017",
        "prenom": "",
        "nomen_long": {
            "text": "LA PASSION DU PAIN",
            "nom": "LA PASSION DU PAIN",
            "initial": "LPDP"
        },
        "indrep": ""
    }
}

Output

{'_score': 1.0, '_index': 'sirene_prod', '_id': 'AXSp612eur2DngRir4BH', '_type': 'sirene_prod', '_surce_enseigne': '', 'codpos_cp': '17300', 'codpos_bur_distrib': '300', 'codpos_depet': '17', '_soure_id': 'ddf9e5b2aa0099ff6934a3d83b1678f64e27859e377362ef8682a9b1', '_source_l3_normalisee': '', '_surce_apet700': '10.71C', '_source_sigle': '', '_source_siren': '793120569', '_source_libapen': 'Bouangerie et boulangerie-patisserie', '_source_apen700': '10.71C', '_source_cedex': '', '_source_typvie': 'AV', '_source_numvoie': 33, '_source_nom': '', '_source_depet_limit': ['16', '24', '33', '79' '85'], '_source_libcom': 'ROCHEFORT', 'l2_normalisee_text': '', 'l2_normalisee_nom': '', 'l2_normamalisee_initial': '', '_source_libvoie': 'GAMBETTA', '_source_nic': '00017', '_source_prenom': '', renom': '', 'nomen_long_text': 'LA PASSION DU PAIN', 'nomen_long_nom': 'LA PASSION DU P_long_initiaAIN', 'nomen_long_initial': 'LPDP', '_source_indrep': ''}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
181 views
Welcome To Ask or Share your Answers For Others

1 Answer

Here is an iterative solution, which should be faster than your current, recursive solution:

def flatten_json_iterative(nested):
    flattened = {}
    stack = [(nested, "")]
    push_to_stack = stack.append
    pop_from_stack = stack.pop
    while stack:
        nested_dict, superior_key = pop_from_stack()
        for key, value in nested_dict.items():
            if isinstance(value, dict):
                push_to_stack((value, f"{key}_"))
            else:
                flattened[f"{superior_key}{key}"] = value
    return flattened

In the repl:

In [8]: flatten_json_iterative(data)
Out[8]:
{'_score': 1.0,
 '_index': 'sirene_prod',
 '_id': 'AXSp612eur2DngRir4BH',
 '_type': 'sirene_prod',
 '_source_enseigne': '',
 '_source_id': 'ddf9e5b2aa0099ff6934a3d83b1678f64e27859e377362ef8682a9b1',
 '_source_l3_normalisee': '',
 '_source_apet700': '10.71C',
 '_source_sigle': '',
 '_source_siren': '793120569',
 '_source_libapen': 'Boulangerie et boulangerie-patisserie',
 '_source_apen700': '10.71C',
 '_source_cedex': '',
 '_source_typvoie': 'AV',
 '_source_numvoie': 33,
 '_source_nom': '',
 '_source_depet_limit': ['16', '24', '33', '79', '85'],
 '_source_libcom': 'ROCHEFORT',
 '_source_libvoie': 'GAMBETTA',
 '_source_nic': '00017',
 '_source_prenom': '',
 '_source_indrep': '',
 'nomen_long_text': 'LA PASSION DU PAIN',
 'nomen_long_nom': 'LA PASSION DU PAIN',
 'nomen_long_initial': 'LPDP',
 'l2_normalisee_text': '',
 'l2_normalisee_nom': '',
 'l2_normalisee_initial': '',
 'codpos_cp': '17300',
 'codpos_bur_distrib': '300',
 'codpos_depet': '17'}

BTW:

Your approach wasn't working because you were checking if nested_dict is a dict then recursing on it, if type(nested_dict) is dict instead, you would want to check if the value is a dict, then recurse on it. But that isn't going to help you much. I am not clever enough to figure out a way to use recursion and a, say, dict comprehension to flatten a nested dictionary like this.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...