for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
Я пытаюсь перебрать словарь и распечатать все пары «ключ-значение», где значение не является вложенным словарем. Если значение является словарем, я хочу войти в него и распечатать его пары ключ-значение ... и т. Д. Любая помощь?
РЕДАКТИРОВАТЬ
Как насчет этого? Он по-прежнему печатает только одно.
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
Полный тестовый пример
Словарь:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
Результат:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
python
dictionary
Takkun
источник
источник
dict
в качестве имени переменной. Никогда не делайте этого (вот почему это не удается).Ответы:
Как сказал Никлас, вам нужна рекурсия, то есть вы хотите определить функцию для печати вашего dict, и если значение является dict, вы хотите вызвать свою функцию печати, используя этот новый dict.
Что-то вроде :
источник
Если вы напишете собственную рекурсивную реализацию или итерационный эквивалент со стеком , возникнут потенциальные проблемы . См. Этот пример:
В обычном смысле вложенный словарь представляет собой структуру данных, подобную n-нному дереву. Но определение не исключает возможности перекрестного ребра или даже заднего ребра (таким образом, это уже не дерево). Например, здесь key2.2 содержит словарь из key1 , key2.3 указывает на весь словарь (задний край / цикл). Когда есть задний край (цикл), стек / рекурсия будет работать бесконечно.
Если вы распечатаете этот словарь с помощью этой реализации от Scharron
Вы увидите эту ошибку:
То же самое и с реализацией от senderle .
Точно так же вы получаете бесконечный цикл с этой реализацией от Фреда Фу :
Однако Python фактически обнаруживает циклы во вложенном словаре:
«{...}» - это место, где обнаружен цикл.
По просьбе Moondra это способ избежать циклов (DFS):
источник
def myprint(d): stack = d.items() visited = set() while stack: k, v = stack.pop() if isinstance(v, dict): if k not in visited: stack.extend(v.iteritems()) else: print("%s: %s" % (k, v)) visited.add(k)
list(d.items())
as,d.items()
возвращая представление, а не список, и используйтеv.items()
вместоv.iteritems()
Поскольку a
dict
является итерируемым, вы можете применить к этой проблеме классическую итеративную формулу вложенного контейнера, сделав лишь пару незначительных изменений. Вот версия Python 2 (см. 3 ниже):Тест:
В Python 2 можно было бы создать кастом,
Mapping
который квалифицируется как,Mapping
но не содержитiteritems
, и в этом случае это не удастся. В документации не указано, чтоiteritems
требуется дляMapping
: с другой стороны, источник предоставляетMapping
типамiteritems
метод. Так что для обычаев на всякий случайMappings
наследуйте отcollections.Mapping
явно.В Python 3 необходимо внести ряд улучшений. Начиная с Python 3.3, абстрактные базовые классы живут в
collections.abc
. Ониcollections
тоже остаются для обратной совместимости, но лучше, если наши абстрактные базовые классы объединены в одном пространстве имен. Итак, это импортabc
изcollections
. Также добавляет Python 3.3yield from
, который разработан как раз для такого рода ситуаций. Это не пустой синтаксический сахар; это может привести к более быстрому коду и более разумному взаимодействию с сопрограммами .источник
isinstance(item, collections.Iterable)
нет гарантииhasattr(item, "iteritems")
. Проверятьcollections.Mapping
лучше.Iterable
сделает это решение более универсальным, забыв о том, что, очевидно, итерации не обязательно должны бытьiteritems
.yield from
синтаксис.Альтернативное итеративное решение:
источник
list
)deque
очередью или даже очередью с приоритетом.Немного другая версия, которую я написал, отслеживает ключи по пути, чтобы добраться туда
На ваших данных он напечатает
Его также легко изменить, чтобы отслеживать префикс как кортеж ключей, а не строку, если он вам так нужен.
источник
Вот питонический способ сделать это. Эта функция позволит вам перебирать пару ключ-значение на всех уровнях. Он не сохраняет все это в памяти, а скорее проходит через dict, когда вы его просматриваете
Печать
источник
Альтернативное решение для работы со списками на основе решения Шаррона
источник
Итерационное решение как альтернатива:
источник
O(depth)
для рекурсивного решения. То же относится и к этой версии, если я правильно думаю).iters
явный стек, поэтому потребление памяти Big-O такое же, или мне что-то не хватает?Я использую следующий код для печати всех значений вложенного словаря с учетом того, где значение может быть списком, содержащим словари. Это было полезно для меня при разборе файла JSON в словарь и необходимости быстро проверить, соответствуют ли какие-либо из его значений
None
.Вывод:
источник
Вот модифицированная версия ответа Фреда Фу для Python 2. В исходном ответе выводится только самый глубокий уровень вложенности. Если вы выводите ключи в виде списков, вы можете сохранить ключи для всех уровней, хотя для того, чтобы ссылаться на них, вам нужно ссылаться на список списков.
Вот функция:
Чтобы сослаться на ключи:
для трехуровневого словаря.
Вам необходимо знать количество уровней, прежде чем получить доступ к нескольким ключам, и количество уровней должно быть постоянным (можно добавить небольшой фрагмент скрипта для проверки количества уровней вложенности при итерации значений, но я не пока смотрел на это).
источник
Я считаю этот подход немного более гибким, здесь вы просто предоставляете функцию генератора, которая генерирует пары ключ-значение и может быть легко расширена, чтобы также перебирать списки.
Затем вы можете написать свою собственную
myprint
функцию, а затем распечатать эти пары ключ-значение.Тест:
Вывод:
Я тестировал это на Python 3.6.
источник
Эти ответы работают только для 2-х уровней подклассов. Для получения дополнительной информации попробуйте следующее:
источник