Сглаживание списка диктов списков диктов (и т. Д.) Неизвестной глубины в Python (кошмарная структура JSON) - PullRequest
6 голосов
/ 12 декабря 2011

Я имею дело со структурой JSON, которая выводится мне в таких структурах:

[{u'item': u'something',
  u'data': {
            u'other': u'',
            u'else':
               [
                  {
                    u'more': u'even more',
                    u'argh':
                         {
                            ...etc..etc

Как видите, это вложенные диктанты и списки. Существует много дискуссий по поводу их рекурсивного сглаживания, но я пока не нашел ни одного, который мог бы иметь дело со списком словарей, который в свою очередь может содержать словари списков, списки списков, словари словарей и т. Д .; которые неизвестной глубины! В некоторых случаях глубина может быть до 100 или около того. Я пробовал это до сих пор без особой удачи (python 2.7.2):

def flatten(structure):
    out = []
    for item in structure:
        if isinstance(item, (list, tuple)):
            out.extend(flatten(item))
        if isinstance(item, (dict)):
            for dictkey in item.keys():
                out.extend(flatten(item[dictkey]))
        else:
            out.append(item)
    return out

Есть идеи?

UPDATE Это в значительной степени работает:

def flatten(l):
    out = []
    if isinstance(l, (list, tuple)):
        for item in l:
            out.extend(flatten(item))
    elif isinstance(l, (dict)):
        for dictkey in l.keys():
            out.extend(flatten(l[dictkey]))
    elif isinstance(l, (str, int, unicode)):
        out.append(l)
    return out

1 Ответ

11 голосов
/ 12 декабря 2011

Поскольку глубина ваших данных произвольна, проще использовать рекурсию, чтобы сгладить ее.Эта функция создает плоский словарь с указанием пути к каждому элементу данных в качестве ключа, чтобы избежать коллизий.

Вы можете получить его содержимое позже, например, с помощью for key in sorted(dic_.keys()).

Я не проверял его, поскольку вы не предоставили «действительный» фрагмент своих данных.

def flatten(structure, key="", path="", flattened=None):
    if flattened is None:
        flattened = {}
    if type(structure) not in(dict, list):
        flattened[((path + "_") if path else "") + key] = structure
    elif isinstance(structure, list):
        for i, item in enumerate(structure):
            flatten(item, "%d" % i, path + "_" + key, flattened)
    else:
        for new_key, value in structure.items():
            flatten(value, new_key, path + "_" + key, flattened)
    return flattened
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...