通过列表字典的递归函数

Recursive Function through dict of lists

给定这个数据结构

[{'name': 'Business Operations', 
  'team_edit': ['BusinessOperations'], 
  'team_view': ['Snaptest'], 
  'test_sub_subfolder': [
       {'name': 'test_sub', 
        'team_edit': ['BusinessOperations', 'Freddy'], 
        'team_view': ['hugo']}], 
  'test_sub2_subfolder': [
       {'name': 'test_sub2', 
        'test_sub_subfolder': [
            {'name': 'test_sub_sub', 
             'team_edit': ['BusinessOperations', 'Freddy'], 
             'team_view': ['hugo']}]}]}]

我正在尝试编写一个递归函数,使我能够访问所有元素,本质上是将它们打印出来。嵌套结构可以是任意长度,但将始终遵循此格式。

我的第一次尝试是

def recurse_over_object(dict_obj):
    for key, value in dict_obj.items():
        if 'subfolder' in key:
            for pair in recurse_over_object(value[0]):
                print(key, *pair)
                # yield (key, *pair)
        else:
            print(key, value)
            # yield (key, value)

这里的问题是,当我沿着树向下走时,我要求值 subfolder 并沿着那条路线走,但在这个例子中,我有两个子文件夹在同一级别(test_subtest_sub2),我需要为它们获取值。

有谁知道有什么奇特的方法可以做到这一点吗? 如果需要,我绝对可以重组数据输入以使其更容易,例如,我的一个想法是将同一级别的子文件夹设置为 list 但后来我在一个递归函数中苦苦挣扎以遍历这些元素。

任何想法的帮助将不胜感激。

您可以在 if 'subfolder' in key: 下迭代调用 recurse_over_object。所以喜欢:

def recurse_over_object(dict_obj):
    for key, value in dict_obj.items():
        if 'subfolder' in key:
            for item in value:
                recurse_over_object(item)
        else:
            print(key, value)

然后

for d in data:
    recurse_over_object(d)

输出:

name Business Operations
team_edit ['BusinessOperations']
team_view ['Snaptest']
name test_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']
name test_sub2
name test_sub_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']

为了跟随您对 yield()(以及 print)的使用,这里是经过调整的代码,我认为它可以满足您的问题。请注意,最后的 x = list( ... ) 语句旨在调用您的函数创建的生成器。

dataStructure = [
    {'name': 'Business Operations', 
     'team_edit': ['BusinessOperations'],
     'team_view': ['Snaptest'], 
     'test_sub_subfolder': [
         {'name': 'test_sub', 
          'team_edit': ['BusinessOperations', 'Freddy'], 
          'team_view': ['hugo']}], 
     'test_sub2_subfolder': [
         {'name': 'test_sub2',
          'test_sub_subfolder': [
              {'name': 'test_sub_sub', 
               'team_edit': ['BusinessOperations', 'Freddy'], 
               'team_view': ['hugo']}]}]}
]
def recurse_over_object(dict_obj):
    for key, value in dict_obj.items():
        if 'subfolder' in key:
            '''
            for pair in recurse_over_object(value[0]):
                print(key, *pair)
                yield (key, *pair)
            '''
            print(key, *list(recurse_over_object(value[0])))
            yield(key, *list(recurse_over_object(value[0])))
        else:
            print(key, value)
            yield (key, value)   

x = list(recurse_over_object(dataStructure[0]))

输出:

name Business Operations
team_edit ['BusinessOperations']
team_view ['Snaptest']
name test_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']
test_sub_subfolder ('name', 'test_sub') ('team_edit', ['BusinessOperations', 'Freddy']) ('team_view', ['hugo'])
name test_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']
name test_sub2
name test_sub_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']
test_sub_subfolder ('name', 'test_sub_sub') ('team_edit', ['BusinessOperations', 'Freddy']) ('team_view', ['hugo'])
name test_sub_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']
test_sub2_subfolder ('name', 'test_sub2') ('test_sub_subfolder', ('name', 'test_sub_sub'), ('team_edit', ['BusinessOperations', 'Freddy']), ('team_view', ['hugo']))
name test_sub2
name test_sub_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']
test_sub_subfolder ('name', 'test_sub_sub') ('team_edit', ['BusinessOperations', 'Freddy']) ('team_view', ['hugo'])
name test_sub_sub
team_edit ['BusinessOperations', 'Freddy']
team_view ['hugo']

您有一个包含列表、字典和字符串的嵌套结构。递归函数可以测试它来决定如何处理元素:

def get_branches(x, acc=()):
    if isinstance(x, dict):
        for k,v in x.items():
            yield from get_branches(v, acc+(k,))
    elif isinstance(x, list):
        for k in x:
            yield from get_branches(k, acc)
    else:
        yield acc + (x,)

x = [{'name': 'Business Operations', 
  'team_edit': ['BusinessOperations'], 
  'team_view': ['Snaptest'], 
  'test_sub_subfolder': [
       {'name': 'test_sub', 
        'team_edit': ['BusinessOperations', 'Freddy'], 
        'team_view': ['hugo']}], 
  'test_sub2_subfolder': [
       {'name': 'test_sub2', 
        'test_sub_subfolder': [
            {'name': 'test_sub_sub', 
             'team_edit': ['BusinessOperations', 'Freddy'], 
             'team_view': ['hugo']}]}]}]

print(list( get_branches(x) ))

输出:

[('name', 'Business Operations'),
 ('team_edit', 'BusinessOperations'),
 ('team_view', 'Snaptest'),
 ('test_sub_subfolder', 'name', 'test_sub'),
 ('test_sub_subfolder', 'team_edit', 'BusinessOperations'),
 ('test_sub_subfolder', 'team_edit', 'Freddy'),
 ('test_sub_subfolder', 'team_view', 'hugo'),
 ('test_sub2_subfolder', 'name', 'test_sub2'),
 ('test_sub2_subfolder', 'test_sub_subfolder', 'name', 'test_sub_sub'),
 ('test_sub2_subfolder', 'test_sub_subfolder', 'team_edit', 'BusinessOperations'),
 ('test_sub2_subfolder', 'test_sub_subfolder', 'team_edit', 'Freddy'),
 ('test_sub2_subfolder', 'test_sub_subfolder', 'team_view', 'hugo')
]