从预定义的数据结构连接序列

时间:2010-10-01 20:45:09

标签: python recursion

我一直在努力构建这段代码,我想知道是否还有其他更简单/有效的方法:

fsSchema = {'published': {'renders': {'SIM': ('fold1', 'fold2'), 'REN': ('fold1', 'fold2')}}}


def __buildPathFromSchema(self, schema, root=''):        
    metaDirs = []
    for dir_ in schema.keys():
        root = os.path.join(root, dir_)
        if isinstance(schema[dir_], dict):
            return self.__buildPathFromSchema(schema[dir_], root)

        if isinstance(schema[dir_], tuple):
            for i in schema[dir_]:
                bottom = os.path.join(root, i)
                metaDirs.append(bottom)
            root = os.sep.join(os.path.split(root)[:-1])
    return metaDirs

基本上我想做的是从fsSchema等预定义结构生成路径。请注意,最新的迭代始终是一个元组。

输出看起来像:

  

[ '出版\呈现\ REN \ fold1',   '出版\渲染\ REN \ fold2',   '出版\渲染\ SIM \ fold1',   '出版\呈现\ SIM \ fold2']

谢谢!

3 个答案:

答案 0 :(得分:3)

您可以使用递归函数生成所有路径:

def flatten(data):
   if isinstance(data, tuple):
      for v in data:
         yield v
   else:
      for k in data:
         for v in flatten(data[k]):
            yield k + '\\' + v

这应该能够处理任何类型的嵌套字典:

>>> fsSchema = {'published': {'renders': {'SIM': ('fold1', 'fold2'), 'REN': ('fold1', 'fold2')}}}
>>> list(flatten(fsSchema))
['published\\renders\\REN\\fold1', 'published\\renders\\REN\\fold2', 'published\\renders\\SIM\\fold1', 'published\\renders\\SIM\\fold2']

请注意,路径是以“随机”顺序生成的,因为词典没有任何内部排序。

答案 1 :(得分:1)

而不是:

for dir_ in schema.keys():
    ...
    if isinstance(schema[dir_], dict):

你可以这样做:

for dir_name, dir_content in schema.iteritems():
    ...
    if isinstance(dir_content, tuple):

它既快又可读。

答案 2 :(得分:1)

我会继续像你已经那样递归地进行,但是将步行器从路径生成器中分离出来:

def walk(data):
    if hasattr(data, 'items'):
        for outer_piece, subdata in data.items():
            for inner_piece in walk(subdata):
                yield (outer_piece, ) + inner_piece
     else:
         for piece in data:
             yield (piece, )

def paths(data):
    for path in walk(data):
        yield os.sep.join(path)

原因在于它实际上是两个独立的功能部件,并且将它们作为单独的功能实现,因此更容易调试,维护,实现并且通常可以考虑。