Go语言实现清理仅含空文件夹的目录树结构
解决方案:清理仅含空文件夹的目录树
核心思路
要解决这个问题,关键是后序遍历目录树——先处理所有子节点,再判断当前节点是否需要保留。这样就能实现回溯:如果某个文件夹的所有子节点都被清理掉(全是空文件夹),那这个父文件夹也要被移除。
具体规则:
- 先递归清理每个子节点,只保留有效节点(文件或非空文件夹)
- 对于当前节点:
- 如果是文件(比如
file1.txt,可通过Id后缀或标识判断),直接保留 - 如果是文件夹,只有清理后还有子节点才保留,否则丢弃
- 如果是文件(比如
完整代码实现
import "strings" type Node struct { Id string Children []Node } // cleanEmptyFolders 清理单个节点下的空文件夹分支,返回处理后的节点(不需要保留则返回nil) func cleanEmptyFolders(node Node) *Node { // 递归处理所有子节点,收集有效子节点 var cleanedChildren []Node for _, child := range node.Children { if cleanedChild := cleanEmptyFolders(child); cleanedChild != nil { cleanedChildren = append(cleanedChildren, *cleanedChild) } } // 更新当前节点的子节点为清理后的结果 node.Children = cleanedChildren // 判断是否为文件(这里通过Id包含后缀判断,可根据实际逻辑修改) if isFile(node) { return &node } // 文件夹只有在有有效子节点时才保留 if len(node.Children) == 0 { return nil } return &node } // cleanRootFolders 清理根节点列表中的空文件夹分支 func cleanRootFolders(roots []Node) []Node { var cleanedRoots []Node for _, root := range roots { if cleanedRoot := cleanEmptyFolders(root); cleanedRoot != nil { cleanedRoots = append(cleanedRoots, *cleanedRoot) } } return cleanedRoots } // isFile 判断节点是否为文件,可根据实际需求调整(比如新增Type字段) func isFile(node Node) bool { return strings.Contains(node.Id, ".") }
代码说明
- 后序遍历的作用:确保处理父节点前,所有子节点都已经完成清理。比如你的例子中,
folder4被判定为空文件夹后返回nil,folder3的子节点变为空,也会被丢弃,以此类推直到folder2被丢弃,最终folder1只保留file1.txt。 - 新树创建:所有节点都是基于原节点复制修改,不会改动原树结构,符合你的要求。
- 效率:每个节点仅被遍历处理一次,时间复杂度为O(n),n是节点总数,属于高效实现。
对比初始代码的问题
你的初始用了前序遍历,先处理父节点再处理子节点,而且没有判断清理后子节点是否为空,所以只能保留原本有子节点的父节点,无法回溯移除那些子节点全被清理的空文件夹。
内容的提问来源于stack exchange,提问作者Laterneman
相关产品推荐
相关产品推荐

