特定の条件に一致する辞書全体を再帰的に調べて削除する必要がある、ネストされたリストと辞書のツリーがあります。たとえば、「タイプ」が「フォルダ」で、子がない (または子の空のリスト) 辞書をすべて削除する必要があります。
私はまだ初心者のPythonistなので、力ずくで許してください。
簡単にコピー アンド ペーストできるように書式設定されたサンプル辞書を次に示します。
{'children': [{'children': [{'key': 'group-1',
'name': 'PRD',
'parent': 'dc-1',
'type': 'Folder'},
{'children': [{'key': 'group-11',
'name': 'App1',
'parent': 'group-2',
'type': 'Folder'}],
'key': 'group-2',
'name': 'QA',
'parent': 'dc-1',
'type': 'Folder'},
{'key': 'group-3',
'name': 'Keep',
'parent': 'dc-1',
'type': 'Host'}],
'key': 'dc-1',
'name': 'ABC',
'parent': 'root',
'type': 'Datacenter'}],
'key': 'root',
'name': 'Datacenters',
'parent': None,
'type': 'Folder'}
このディクショナリでは、/root/dc-1/group-3 だけを残す必要があります。group-11 フォルダーを最初に削除し、次にその親 (子はもう存在しないため) などを削除する必要があります。
さまざまな再帰的方法を試しましたが、適切に機能させることができないようです。どんな助けでも大歓迎です。
def cleanup(tree):
def inner(tree):
if isinstance(tree, dict):
if 'type' in tree and tree['type'] == 'Folder':
if 'children' not in tree or not tree['children']:
print 'Deleting tree: ' + str(tree['name'])
if str(tree['key']) not in del_nodes:
del_nodes.append(str(tree['key']))
else:
for item in tree.values():
inner(item)
# Delete empty folders here
if del_nodes:
print 'Perform delete here'
if 'children' in tree and isinstance(tree['children'], (list, tuple)):
getvals = operator.itemgetter('key')
tree['children'].sort(key=getvals)
result = []
# groupby is the wrong method. I need a list of tree['children'] that doesn't contain keys in del_nodes
for k, g in itertools.groupby(tree['children'], getvals):
result.append(g.next())
tree['children'][:] = result
del_nodes = []
else:
for item in tree.values():
inner(item)
elif isinstance(tree, (list, tuple)):
for item in tree:
inner(item)
if isinstance(item, dict):
if 'type' in item and item['type'] == 'Folder':
if 'children' not in item or not item['children']:
print 'Delete ' + str(item['name'])
if str(item['key']) not in del_nodes:
del_nodes.append(str(item['key']))
elif isinstance(item, (list, tuple)):
if not item:
print 'Delete ' + str(item['name'])
if str(item['key']) not in del_nodes:
del_nodes.append(str(item['key']))
inner(tree)