【问题标题】:Recursively make directories: search for recursion递归地制作目录:搜索递归
【发布时间】:2021-02-16 00:40:19
【问题描述】:

我有一个目录名称列表:

dirnames = ["foo/bar", "foo/bar/mydir", "bar/mydir", "bar"]

我想(递归地)创建所有目录。只需递归地创建最深的目录就足够了。在这种情况下,就足够了:

os.makedirs("foo/bar/mydir")
os.makedirs("bar/mydir")

问题:如何减少dirnames 只拥有最深的目录?

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 一个简单的 for 循环创建所有目录的复杂度为 O(n)。如果算法比 O(n) 更差,那么缩短到仅最深的目录实际上会花费您的时间(在 Big Oh 的意义上)。
  • sorted([(len(i.split('/')), i) for i in dirnames])[-2:] 将给出前 2 个最深的目录名
  • @deadshot 我认为我的失败尝试不会改善这个问题。我开始写太复杂的东西,结果方向错误,请参阅下面的好答案。事后看来,这个问题可能应该通过省略上下文来缩短。

标签: python


【解决方案1】:

虽然其他人已经发布了非常有用的迭代解决方案,但这里有一种可以递归选择完整目录的方法:

from collections import defaultdict
def to_tree(d):
  t = defaultdict(list)
  for a, *b in d:
     t[a].append(b)
  return {a:None if not (k:=list(filter(None, b))) else to_tree(k) for a, b in t.items()}

def get_paths(d, c = []):
  for a, b in d.items():
     if b is None:
        yield '/'.join(c+[a])
     else:
        yield from get_paths(b, c + [a])


dirnames = ["foo/bar", "foo/bar/mydir", "bar/mydir", "bar"]
print(list(get_paths(to_tree([i.split('/') for i in dirnames]))))

输出:

['foo/bar/mydir', 'bar/mydir']

【讨论】:

  • 这真的很棒。我认为defaultdict 的解决方案非常聪明!
【解决方案2】:
dirnames = ["foo/bar", "foo/bar/mydir", "bar/mydir", "bar","foo/bar/dir2"]
from itertools import groupby
import heapq
d=[sorted(list(g)) for (k,g) in groupby(sorted(dirnames), key= lambda x: x.split('/')[0])]
[max(elem) for elem in d]

或者如果你需要 2 的深度

[heapq.nlargest(2, elem) for elem in d]

在父目录上使用groupby。即foobar。如果我们使用max,我们只会得到foo/bar/mydir,因为它的长度比foo/bar/dir2 长。 为了避免这种情况,我们可以得到heapq,但这将是一个矫枉过正。额外的 if 子句可用于检查 inner list 是否有 len >2

【讨论】:

  • 太好了!非常感谢!
  • 我想当列表更复杂的时候我应该只是递归调用那个操作
  • [os.makedirs(max(elem)) for elem in d]你可以这样做..你的目录将被创建
猜你喜欢
  • 2016-09-06
  • 2013-06-17
  • 2011-08-15
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多