拼合嵌套字典,将字典嵌入列表中(功能强大的python)

时间:2019-04-03 21:14:11

标签: python json dictionary flatten

这个问题已经问了很多遍了-但是在这种特殊情况下只问过一次,我可以部分找到答案here,但是它会缩小到每个对象。

我有这本字典:

{'address': {'address_line_1': 'Floor Dekk House',
  'address_line_2': 'Zippora Street Providence Industrial Estate',
  'country': 'Seychelles',
  'locality': 'Mahe',
  'premises': '1st'},
 'address_snippet': '1st, Floor Dekk House, Zippora Street Providence Industrial Estate, Mahe, Seychelles',
 'appointment_count': 1,
 'description': 'Total number of appointments 1',
 'description_identifiers': ['appointment-count'],
 'kind': 'searchresults#officer',
 'links': {'self': '/officers/z7s5QUnhlYpAT8GvqvJ5snKmtHE/appointments'},
 'matches': {'snippet': [], 'title': [1, 8, 10, 11]},
 'snippet': '',
 'title': 'ASTROCOM AG '}

您可以看到"description_identifiers""matches.snippet""matches.title" have a list as value. I'd like to edit my code below to flatten my dictionary so that the json is flattened in a {key:value,key:value,key:value}`对-但如果值是原子对象的列表(而不是列表列表或字典列表),该值将保留为列表。

目标是能够将json上载到postgresql。

以下是我在网上找到的一些代码:

def flatten_json(dictionary):
    """Flatten a nested json file"""

    def unpack(parent_key, parent_value):
        """Unpack one level of nesting in json file"""
        # Unpack one level only!!!

        if isinstance(parent_value, dict):
            for key, value in parent_value.items():
                temp1 = parent_key + '_' + key
                yield temp1, value
        elif isinstance(parent_value, list):
            i = 0 
            for value in parent_value:
                temp2 = parent_key + '_' +str(i) 
                i += 1
                yield temp2, value
        else:
            yield parent_key, parent_value    


    # Keep iterating until the termination condition is satisfied
    while True:
        # Keep unpacking the json file until all values are atomic elements (not dictionary or list)
        dictionary = dict(chain.from_iterable(starmap(unpack, dictionary.items())))
        # Terminate condition: not any value in the json file is dictionary or list
        if not any(isinstance(value, dict) for value in dictionary.values()) and \
           not any(isinstance(value, list) for value in dictionary.values()):
            break

    return dictionary

所需的输出:

为了测试,该命令: 不是(应该是我现在得到的):

{'address_address_line_1': 'Floor Dekk House',
 'address_address_line_2': 'Zippora Street Providence Industrial Estate',
 'address_country': 'Seychelles',
 'address_locality': 'Mahe',
 'address_premises': '1st',
 'address_snippet': '1st, Floor Dekk House, Zippora Street Providence Industrial Estate, Mahe, Seychelles',
 'appointment_count': 1,
 'description': 'Total number of appointments 1',
 'description_identifiers_0': 'appointment-count',
 'kind': 'searchresults#officer',
 'links_self': '/officers/z7s5QUnhlYpAT8GvqvJ5snKmtHE/appointments',
 'matches_title_0': 1,
 'matches_title_1': 8,
 'matches_title_2': 10,
 'matches_title_3': 11,
 'snippet': '',
 'title': 'ASTROCOM AG '}

但是相反

{'address_address_line_1': 'Floor Dekk House',
 'address_address_line_2': 'Zippora Street Providence Industrial Estate',
 'address_country': 'Seychelles',
 'address_locality': 'Mahe',
 'address_premises': '1st',
 'address_snippet': '1st, Floor Dekk House, Zippora Street Providence Industrial Estate, Mahe, Seychelles',
 'appointment_count': 1,
 'description': 'Total number of appointments 1',
 'description_identifiers_0': 'appointment-count',
 'kind': 'searchresults#officer',
 'links_self': '/officers/z7s5QUnhlYpAT8GvqvJ5snKmtHE/appointments',
 'matches_title': [1, 8, 10, 11]
 'snippet': '',
 'title': 'ASTROCOM AG '}

1 个答案:

答案 0 :(得分:1)

您几乎完成了,只是您需要对情况进行更多检查:

def flatten(dict_, prefix):
    for k, v in dict_.items():
        if isinstance(v, list) and len(v)==1:
            if isinstance(v[0], dict):
                for key, value in flatten(v[0], prefix+k+"_"):
                    yield key, value
            else:
                yield prefix+k+"_0", v[0]
        elif isinstance(v, dict):
            for key, value in flatten(v, prefix+k+"_"):
                yield key, value
        else:
            yield prefix+k, v

用法:

dict_ = {'address': {'address_line_1': 'Floor Dekk House',
  'address_line_2': 'Zippora Street Providence Industrial Estate',
  'country': 'Seychelles',
  'locality': 'Mahe',
  'premises': '1st'},
 'address_snippet': '1st, Floor Dekk House, Zippora Street Providence Industrial Estate, Mahe, Seychelles',
 'appointment_count': 1,
 'description': 'Total number of appointments 1',
 'description_identifiers': ['appointment-count'],
 'kind': 'searchresults#officer',
 'links': {'self': '/officers/z7s5QUnhlYpAT8GvqvJ5snKmtHE/appointments'},
 'matches': {'snippet': [], 'title': [1, 8, 10, 11]},
 'snippet': '',
 'title': 'ASTROCOM AG '}

import json
print(json.dumps(dict(list(flatten(dict_, ""))), indent=4))

输出:

{
    "address_address_line_1": "Floor Dekk House",
    "address_address_line_2": "Zippora Street Providence Industrial Estate",
    "address_country": "Seychelles",
    "address_locality": "Mahe",
    "address_premises": "1st",
    "address_snippet": "1st, Floor Dekk House, Zippora Street Providence Industrial Estate, Mahe, Seychelles",
    "appointment_count": 1,
    "description": "Total number of appointments 1",
    "description_identifiers_0": "appointment-count",
    "kind": "searchresults#officer",
    "links_self": "/officers/z7s5QUnhlYpAT8GvqvJ5snKmtHE/appointments",
    "matches_snippet": [],
    "matches_title": [
        1,
        8,
        10,
        11
    ],
    "snippet": "",
    "title": "ASTROCOM AG "
}