在Python中递归遍历列表的子节点

时间:2013-08-16 04:45:32

标签: python recursion

我尝试从嵌套的列表列表中递归打印句子

我想获得一个包含

的列表

['大坏狗','大蓬松猫','小蓝色快乐小马','小青蛙']

这是我的代码,它不起作用......

我是在正确的道路上还是应该以另一种方式构建我的数据以实现我的目标?

from pprint import pprint

dirs = [

{ 
    'kw': 'big',
    'childs': [
        { 
            'kw': 'bad',
            'childs': [
                {
                    'kw': 'dog'
                }
            ]
        },
        {
            'kw': 'fluffy',
            'childs': [
                {
                    'kw': 'cat'
                }
            ]
        }

    ]
},

{ 
    'kw': 'small',
    'childs': [
        { 
            'kw': 'blue',
            'childs': [
                {

                    'kw': 'happy',
                    'childs': [
                        { 
                            'kw': 'pony'

                        }

                    ]
                }
            ]
        },
        {
            'kw': 'frog'

        }

    ]
},
]


def traverse(d, l):

    kw = d.get('kw')
    c = d.get('childs')
    l.append(kw)
    if c:
        for cc in c:
           l = traverse(cc, l)



return l


r = traverse(dirs[0], [])

pprint(r)

5 个答案:

答案 0 :(得分:2)

查看此功能:

def traverse(d, l, s = None):
  kw = d.get('kw')
  c = d.get('childs')
  if(s == None):
     s = kw
  else:
     s = s + " " +kw
  if c:
      for cc in c:
          l = traverse(cc, l, s)
  else:
      l.append(s)

  return l 

它对递归函数的一个非常小的修改:

r = traverse(dirs[0], [])

答案 1 :(得分:2)

像往常一样,生成器与递归结构很好地协同工作

def traverse(i):
    for d in i:
        childs = d.get('childs')
        for j in traverse(childs) if childs else ['']:
            yield d['kw']+' '+j

res = list(traverse(dirs))

在Python3.3中,这变为

def traverse(i):
    for d in i:
        c = d.get('childs')
        yield from (d['kw']+' '+j for j in (traverse(c) if c else ['']))

答案 2 :(得分:0)

这是给定问题的解决方案,dirs是您在上面定义的类似json的结构。它是递归的,它可以工作,它涵盖了像顶层结构是字典的边缘情况。

def traverse(l, al = "", comps = []):
    if isinstance(l,dict):
        if not al:
            al += l.get("kw")
        else:        
            al += ", %s" % l.get("kw")
        traverse(l.get("childs"), al, comps)
    elif isinstance (l,list):
        for i in l:
            traverse(i, al, comps)
    else:
        comps.append(al)
    return comps

print traverse(dirs)

答案 3 :(得分:0)

我会说我的解决方案非常简单(如果你想处理找不到密钥的情况,请更改get的项目查找)

def _traverse(d):
    prefix = d['kw']
    if 'childs' not in d:
        return [prefix]
    results = []
    for subdict in d['childs']:
        subtraversal = _traverse(subdict)
        results.extend(prefix+' '+item for item in subtraversal)
    return results

def traverse(d):
    return list(sum((_traverse(subdict) for subdict in d),[]))

答案 4 :(得分:0)

啊,Gnibbler打败了我的发电机帽子。唯一值得一提的是“.join来拼接句子和*语法以避免测试

def traverse_keys(*dictvalues):
    for dictval in dictvalues:
        for token in traverse_keys(*dictval.get('childs', [])):
            yield token
        kw = dictval.get('kw')
        if kw: yield kw

tokens = [kw for kw in traverse_keys (*dirs)]
tokens.reverse()
print " ".join(tokens)

如果您不希望孩子有多个分支,您可以直接嵌套词典 - 您的逻辑无法选择当前结构中的哪个分支。您可以通过嵌套字典来命名分支:

{ 'kw': 'dog'
  'big': { 'kw': 'scary' } 
  'small': { 'kw': 'yippy',  'fluffy': { 'kw': 'poodle'} }
}

这将使遍历更清洁