简体   繁体   English

递归地遍历Python中列表的子项

[英]Walk recursively through childs of a list in Python

I try to recursively print sentences from a nested list of lists 我尝试从嵌套的列表列表中递归打印句子

I want to obtain a list containing 我想获取一个包含以下内容的列表

['big bad dog', 'big fluffy cat', 'small blue happy pony', 'small frog'] [“大坏狗”,“大蓬松猫”,“小蓝快乐小马”,“小青蛙”]

Here is my code, it don't work... 这是我的代码,它不起作用...

Am I on the right path or I should structure my data in an another way to achieve my goal? 我是在正确的道路上还是应该以另一种方式构造数据以实现目标?

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)

Check out this function: 查看此功能:

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 

Its a very small modification to your recursion function: 它是对递归函数的很小的修改:

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

As usual, generators work nicely with recursive structures 像往常一样,生成器可以很好地与递归结构一起使用

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

In Python3.3, this becomes 在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 ['']))

Here's a solution to the given problem, with dirs being the json like structure you defined above. 这是给定问题的解决方案,其中dirs是您在上面定义的类似于json的结构。 It's recursive, it works and it covers edge cases like the top structure being a dictionary. 它是递归的,可以正常工作,并且涵盖了诸如顶级结构作为字典之类的边缘情况。

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)

I would say my solution is pretty simple (change the item lookup for get if you want to handle cases where the key isn't found) 我想说我的解决方案非常简单(如果要处理未找到密钥的情况,请更改项目查找以获取)

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),[]))

Ah, Gnibbler beat me to the generator hattip. 啊,Gnibbler击败了我。 Only difference worth mentioning is " ".join to stitch the sentence and the *syntax to avoid if tests 唯一值得一提的区别是“ .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)

If you dont expect multiple branches in your children, the you can just nest the dictionaries directly - your logic doesn't have a way to choose which branch in the current structure. 如果您不希望孩子中有多个分支,则可以直接嵌套字典-您的逻辑无法选择当前结构中的哪个分支。 You could have named branches just by nesting dictionaries: 您可以仅通过嵌套字典来命名分支:

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

which would make the traversal cleaner 这将使遍历更干净

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM