Прежде всего, ваше время l oop бесполезно, так как вы всегда сломаете его в конце.
Чтобы получить внуков, вам нужно будет продублировать
if item['parent']:
if item['parent'] not in all_children_of_items:
all_children_of_items[item['parent']] = []
if item['id'] not in all_children_of_items[item['parent']]:
all_children_of_items[item['parent']].append(item['id'])
проверьте внутри себя, чтобы справиться с дедушкой. Если вы хотите обобщить свой код для обработки любого уровня, вам нужно будет повторять этот блок внутри себя для каждого дополнительного уровня, который вы хотите обработать.
Если такое обобщение может потребоваться, рекурсивный подход будет самый простой, такой как следующий код, который также включает в себя этап предварительной обработки для упрощения и оптимизации более позднего кода:
def getChildrenRecursive(items, maxLevel):
''' Returns a dict of item IDs and a list of their children up to maxLevel deep. '''
itemsByID = {}
result = {}
for item in items:
result[item['id']] = []
itemsByID[item['id']] = item
for item in items:
walkParents(result, item, itemsByID, item['id'], 1, maxLevel)
return result
def walkParents(result, item, items, idToAdd, level, maxLevel):
if level > maxLevel:
return
parent = item['parent']
if parent is None:
return
result[parent].append(idToAdd)
parentItem = items[parent]
walkParents(result, parentItem, items, idToAdd, level + 1, maxLevel)
Обратите внимание, что код может быть преобразован в нерекурсивную версию довольно легко, так как использует только хвостовой вызов, но я оставлю это в качестве упражнения для читателя.
Для того, чтобы просто получить детей и внуков, это будет называться как:
items = [
{'id': 1, 'parent': None},
{'id': 2, 'parent': 1},
{'id': 3, 'parent': 2},
{'id': 4, 'parent': None},
{'id': 5, 'parent': 4},
]
getChildrenRecursive(items, 2) # Returns the result. The number is the maximum number of steps to walk.