Расплющить словарь в Python вызов


У меня есть вопрос об этой кодирование проблемой для "расплющить словарь":

Дан словарь dict, написать flattenDictionary функцию, которая возвращает упрощенный вариант .

Если вы используете скомпилированный язык Ява, с++, C#, Swift и идти, вы можете использовать карту/словарь/хэш-таблицу, которая сопоставляет строки (ключи) для универсального типа (например, объект в Java, какой-либо объект в Swift и т. д.) чтобы разрешить вложенные словари.

Пример:

Вход:

dict = {
    "Key1" : "1",
    "Key2" : {
        "a" : "2",
        "b" : "3",
        "c" : {
            "d" : "3",
            "e" : "1"
        }
    }
}

Выход:

{
    "Key1" : "1",
    "Key2.a" : "2",
    "Key2.b" : "3",
    "Key2.c.d" : "3",
    "Key2.c.e" : "1"
}

Важно: когда вы объединить ключи, убедитесь, чтобы добавить точку между ними. Например обьединении Ключ2, C и D ключ результат будет Ключ2.С. д.

def flatten_dictionary(dictionary):

  def items():
  # loop through each item inside the dictionary k, v
      #Appending
      # check if the sub-key and sub-value are 
      # inside the flatten_dict(value)
      # join on subkey array
      # add to result
      # clear out prev_keys
    for key, value in dictionary.items():
      if isinstance(value, dict):
        for subkey, subvalue in flatten_dictionary(value).items():
          if key == "":
            yield subkey, subvalue
          yield key + "." + subkey, subvalue

      else:

        yield key, value

  return dict(items()) 


# test cases 1

dictionary2 = {
            "Key1" : "1",
            "Key2" : {
                "a" : "2",
                "b" : "3",
                "c" : {
                    "d" : "3",
                    "e" : "1"
                }
            }
        }


# output: {
#             "Key1" : "1",
#             "Key2.a" : "2",
#             "Key2.b" : "3",
#             "Key2.c.d" : "3",
#             "Key2.c.e" : "1"
#         }

print(flatten_dictionary(dictionary2))


1166
1
задан 25 января 2018 в 10:01 Источник Поделиться
Комментарии
1 ответ

1. Ошибки


  1. Специальный чехол для пустых ключей:

    if key == "":
    yield subkey, subvalue
    yield key + "." + subkey, subvalue

    отсутствует else: и так приводит к элементам появляться дважды:

    >>> flatten_dictionary({"": {"a":1}})
    {'a': 1, '.a': 1}

  2. Даже если мы исправим ошибку путем добавления else:есть еще проблема. Рассмотрим такой пример:

    >>> flatten_dictionary({"a": {"": {"b": 1}}, "": {"a": {"b": 2}}})
    {'a.b': 2}

    Что случилось с 1? Игнорируя пустые строки ключей привел два разных ключа, чтобы быть свернуты в одну. Было бы лучше убрать в специальный чехол для пустых строк, так что:

    >>> flatten_dictionary({"a": {"": {"b": 1}}, "": {"a": {"b": 2}}})
    {'a..b': 1, '.a.b': 2}

  3. Python имеет ограниченный стек, но словари могут быть вложены произвольно глубоко:

    >>> d = {}
    >>> for i in range(1000): d = {'a':d}
    ...
    >>> flatten_dictionary(d)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "cr186013.py", line 22, in flatten_dictionary
    return dict(items())
    [... many line omitted ...]
    File "cr186013.py", line 13, in items
    for subkey, subvalue in flatten_dictionary(value).items():
    RecursionError: maximum recursion depth exceeded

    Эту проблему можно избежать, используя стек итераторов шаблон.


2. Других точек обзора


  1. Комментарий не соответствует коду: нет ничего в код, соответствующий "проверьте, если открытый ключ и суб-значение внутри flatten_dict(значение)" или "войти в раздел выбора" или "очистить prev_keys". Неправильные подобные комментарии хуже, чем бесполезны: они делают это тяжелее, чтобы понять и поддерживать код.

    Сделал этот комментарий, опишите более ранней версии кода, а затем вы изменили код, но забыл отредактировать комментарий? Стоит попасть в привычку менять первый комментарий, так что вы не забывайте.


  2. Строительство ключи результате ненужные квадратичное время выполнения. Например, в такой ситуации:

    >>> flatten_dictionary({'a': {'a': {'a': {'a': {'a': {'a': 1}}}}}})
    {'a.a.a.a.a.a': 1}

    есть только необходимость объединить результат один ключ ('a.a.a.a.a.a'), но код объединяет пять ключей результат: не только та, которая нам нужна, но 'a.a', 'a.a.a', 'a.a.a.aи 'a.a.a.a.a' как хорошо. Способ избежать этого-сохранить стек словарь ключей в данный момент, и использовать str.join на стек, когда нужно сцепить результат ключ.


3. Пересмотренный кодекс

def flatten_dictionary(d):
result = {}
stack = [iter(d.items())]
keys = []
while stack:
for k, v in stack[-1]:
keys.append(k)
if isinstance(v, dict):
stack.append(iter(v.items()))
break
else:
result['.'.join(keys)] = v
keys.pop()
else:
if keys:
keys.pop()
stack.pop()
return result

2
ответ дан 27 января 2018 в 01:01 Источник Поделиться