#python
#питон #python
Вопрос:
У меня есть ветвящийся вложенный словарь для визуализации данных таксономии видов. Я пытаюсь написать функцию, которая выдает мне все ветви на определенном уровне.
Я пробовал итеративные и рекурсивные функции, но я приблизился только к использованию рекурсивной функции. Однако, в зависимости от того, куда я помещаю инструкции return
/ print
, моя функция либо возвращает None
(но печатает правильную информацию), либо возвращает только одну ветвь данных. Используя второй вариант, вывод идеален до тех пор, пока набор данных не разветвится.
tree = {"k-b":
{"p-a":
{"c-a":{"o-a":{}, "o-b":{}},
"c-b":{"o-a":{}}},
"p-b":
{"c-a":{"o-a":{},"o-b":{}}}}}
def branches(tree, level):
if level == 0:
#print(tree.keys())
return tree.keys()
else:
for i in tree.keys():
return branches(tree[i], level-1)
print(branchNumber(tree, 2))
Я ожидаю, что для уровня 2 [['c-a', 'c-b'], ['c-a']]
(это не обязательно должен быть массив массивов, и мне все равно, есть ли у него dict_keys () или что-то еще вокруг него)
На самом деле я получаю dict_keys(['c-a', 'c-b'])
, что исключает вторую ветвь
В качестве альтернативы, если я удалю ‘return’ перед рекурсивным вызовом ветвей и раскомментирую оператор print, он печатает:
dict_keys(['c-a', 'c-b'])
dict_keys(['c-a'])
Это именно тот результат, который я хочу, но функция возвращает None
поэтому я не могу сохранить эту информацию для будущих приложений
Комментарии:
1. Ваш
return
внутреннийfor
цикл, конечно, возвращается только один раз, для первого элемента в цикле, поэтому вы никогда не увидите другие элементы.
Ответ №1:
Ваш код всегда возвращает первый элемент в цикле, поэтому ваш алгоритм завершается преждевременно и не исследует все необходимые ветви. Вы могли бы yield
использовать результаты для создания функции генератора (среди других подходов):
tree = {"k-b":
{"p-a":
{"c-a":{"o-a":{}, "o-b":{}},
"c-b":{"o-a":{}}},
"p-b":
{"c-a":{"o-a":{},"o-b":{}}}}}
def branches(tree, level):
if level == 0:
yield list(tree.keys())
elif level > 0:
for v in tree.values():
yield from branches(v, level - 1)
for i in range(4):
print(f"level {i}:", list(branches(tree, i)))
Вывод:
level 0: [['k-b']]
level 1: [['p-a', 'p-b']]
level 2: [['c-a', 'c-b'], ['c-a']]
level 3: [['o-a', 'o-b'], ['o-a'], ['o-a', 'o-b']]
Строка elif level > 0:
является оптимизацией, позволяющей избежать углубления в дерево, чем необходимо.
Кроме того, for i in tree.keys()
, тогда tree[i]
доступ к значению мог бы быть понятнее как for v in tree.values()
.
Ответ №2:
Возможно, вы захотите вернуть список всех элементов на этом уровне:
tree = {"k-b":
{"p-a":
{"c-a":{"o-a":{}, "o-b":{}},
"c-b":{"o-a":{}}},
"p-b":
{"c-a":{"o-a":{},"o-b":{}}}}}
def branches(tree, level):
if level == 0:
#print(tree.keys())
return tree.keys()
else:
return [branches(tree[i], level-1) for i in tree.keys()]
print(branches(tree, 2))
Вывод:
[[dict_keys(['c-a', 'c-b']), dict_keys(['c-a'])]]
Ответ №3:
Похоже, вы хотите вернуть список всех ветвей. Один из способов сделать это — использовать понимание списка:
def branches(tree, level):
if level == 0:
#print(tree.keys())
return tree.keys()
else:
return [branches(tree[i], level-1) for i in tree.keys()]
Обратите внимание, что это вернет глубоко вложенный список. Сглаживание оставлено в качестве упражнения для читателя.
Комментарии:
1. Вы уверены, что хотите обернуть список вокруг каждого уровня, по которому вы спускаетесь в дереве? Например.
branches(tree, 3) # => [[[dict_keys(['o-a', 'o-b']), dict_keys(['o-a'])], [dict_keys(['o-a', 'o-b'])]]]