2

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

我想获得一个包含

['大坏狗'、'大毛茸茸的猫'、'小蓝快乐小马'、'小青蛙']

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

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

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)
4

5 回答 5

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], [])
于 2013-08-16T05:10:41.103 回答
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 ['']))
于 2013-08-16T05:45:12.487 回答
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)
于 2013-08-16T05:05:42.330 回答
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),[]))
于 2013-08-16T05:13:49.273 回答
0

啊,Gnibbler 把我打到了发电机的顶峰。唯一值得一提的区别是 " ".join 用于拼接句子和 * 语法以避免 if 测试

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'} }
}

这将使遍历更清洁

于 2013-08-16T05:59:37.437 回答