【问题标题】:Traverse tree initializing variables遍历树初始化变量
【发布时间】:2012-09-17 17:50:53
【问题描述】:

如果您找到更合适的方式来命名此问题的标题,请随时更新。

我有节点

public Class Node
{
    public List<Node> Children = new List<Node>();
    public Node Parent;
    public FileSystemInfo Value;
}

在树中表示一个文件。

现在我想将节点类更改为:

class ScanItem
{
    public List<ScanItem> Children; 
    public ScanItem Parent;

    public long Size;
    public string Name;    
    public string FullPath;
    public bool IsDirectory;
    // etc....    

}

所以我的问题是如何将Node 类对象转换为ScanItem我想存储文件和目录的大小而不仅仅是文件。(节点类只存储文件的大小而不是目录)因此我必须以某种方式递归地跟踪子项大小的总和为了实现我想要的。

到目前为止,我已将此构造函数放在 ScanItem 上:

    public ScanItem(Node node)
    {                        
        this.Name = node.Name;
        this.FullPath = node.Value.FullName;

        foreach(var child in node.Children)
        {
             this.Children.add(new ScanItem(child));
        }
    }

这将使我能够执行转换,但我缺少分配目录的大小......

【问题讨论】:

  • node.Name,node.FullName我在Node中看不到这些属性
  • 修复它。不过这并不重要。我也在初始化构造函数中的其他变量。我感兴趣的唯一变量是目录的大小......
  • 为什么不遍历所有子文件来计算总大小..即使在操作系统中,它们也会在您查询文件夹大小时确定文件夹大小。
  • 想一想:如果 node.Children 在构造函数中为空,那么你会碰到叶子,所以首先设置this.Size = (node.Value is FileInfo) ? ((FileInfo)node.Value).Length : 0,然后使用ScanItem tmp = this; while (tmp.Parent != null) { tmp.Parent.Size += tmp.Size; tmp = tmp.Parent; }“冒泡添加”到根的大小
  • 是的,我喜欢这个主意。每次添加新文件时,我都会触发 buble 事件。那里虽然有很多活动。我下降了 10 级(最高 10 级),然后计划向该目录添加 1000 个文件,然后我将执行 1000*10 事件...

标签: c# recursion tree


【解决方案1】:

要获取目录的大小,您可以使用此扩展方法

public static class DirectoryInfoEx
{
    public static long GetDirectorySize(this DirectoryInfo di)
    {
        long size = 0;

        var fileInfos = di.GetFiles();
        foreach (var fi in fileInfos)
        {
            size += fi.Length;
        }

        var subDirInfos = di.GetDirectories();
        foreach (var subDir in subDirInfos)
        {
            size += GetDirectorySize(subDir);
        }

        return size;
    }
}

如果我理解正确,您只需在 ScanItem 类的构造函数中添加两行代码

public ScanItem(Node node)
{                        
    this.Name = node.Name;
    this.FullPath = node.Value.FullName;
    DirectoryInfo di = new DirectoryInfo(this.FullPath);  //<<<<<<<
    this.Size = di.GetDirectorySize();                    //<<<<<<<

    foreach(var child in node.Children)
    {
         this.Children.add(new ScanItem(child));
    }
}

您可能需要处理一些特殊情况,例如UnauthorizedAccessException。您还可以通过摆脱 公共字段 来改进您的风格,例如将它们转换为 公共自动属性 public long Size{get;set;}

【讨论】:

  • +1 感谢您的帮助。那行得通,但我会找到两次文件,从而使算法慢一倍。我忘了提到我运行了一个递归方法来查找所有文件和目录并返回一个 Node 对象及其对应的子对象。
  • 如果你做了两次 - 缓存它。基本缓存将是一个字典,其中包含您选择的 id 和将被重用的值。你失去了一些记忆,但获得了性能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 2019-04-28
  • 2019-05-17
  • 2021-07-08
  • 2012-06-15
相关资源
最近更新 更多