寻找更快的方法来搜索类列表中的属性

时间:2016-04-02 13:08:33

标签: c#

下面是我用来表示树结构的类,用于显示游戏存档格式的文件和文件夹。

public class DirNode : INotifyPropertyChanged
{
     public String Name { get; set; }
     public int Index { get; private set; }
     public int FileIndex { get; private set; }
     public int Type { get; private set; }
     public List<DirNode> Directories { get; set; }
     public List<FileNode> Files { get; set; }

     public DirNode(String n, int index, int type, int fi)
     {
           Name = n;
           Directories = new List<DirNode>();
           Files = new List<FileNode>();
           Index = index;
           Type = type;
           FileIndex = fi;
     }
}

下面是我正在使用的类的方法,用于将路径字符串解析为树。当我只加载一个存档时它运行得很好,但是当试图“挂载”多个档案时,效率低下肯定显示

 public void AddPath(String[] path, int index, int fileIndex)
        {
            if (path.Length > 1) //It's a Folder;
            {
                bool found = false;
                int i = 0;
                while (i < this.Directories.Count && found == false)//search to see if this folder already exists
                {
                    if (this.Directories[i].Name == path[0])
                    {
                        found = true;
                        String[] newPath = new String[path.Length - 1];
                        Array.Copy(path, 1, newPath, 0, newPath.Length);
                        this.Directories[i].AddPath(newPath, index,fileIndex);
                        return;
                    }

                    i++;
                }
                if (found == false) //new item
                {
                    DirNode dn = new DirNode(path[0], -1, 0,fileIndex);
                    this.Directories.Add(dn);
                    String[] newPath = new String[path.Length - 1];
                    Array.Copy(path, 1, newPath, 0, newPath.Length);
                    this.Directories[this.Directories.Count - 1].AddPath(newPath, index,fileIndex);
                }
            }
            else if (path.Length == 1) //a file!
            {
                DirNode fn = new DirNode(path[0], index, 1,fileIndex);
                this.Directories.Add(fn);
                return;
            }
            else
            {
                //really no reason why we should be here. 
                return;
            }
        }

我知道BinarySearch需要一个预先排序的列表,这个列表不起作用,因为列表在组装树之后才会排序。但它最终是排序的,所以Hash也不会起作用。如果有人有任何想法,我很乐意听到他们的意见。

当然,如果有人知道.NET DirectoryInfo类的虚拟实现,那可能会更好。

1 个答案:

答案 0 :(得分:1)

为什么不将项目存储在插入时排序的目录和文件中,以便您可以在每个目录级别上实际执行二进制搜索? List类中的BinarySearch()将为您提供索引(如果找到)和索引补充(使用~运算符),如果找不到,那么您就知道需要插入新项目的索引程。

像这样的东西(没有以任何方式测试过,只是在编辑器中被黑了):

用于比较两个DirNodes的名称的类:

internal class DirNodeNameComparer: IComparer<DirNode> {
    public static readonly DirNodeNameComparer Default = new DirNodeNameComparer();

    public int Compare(DirNode x, DirNode y) {
        return string.Compare(x.Name, y.Name);
    }
}

更新了您的AddPath方法以保留已排序的表示形式:

public void AddPath(String[] path, int index, int fileIndex)
{
    if (path.Length > 1) //It's a Folder;
    {
        DirNode dn = new DirNode(path[0], -1, 0, fileIndex);
        int i = this.Directories.BinarySearch(dn, DirNodeNameComparer.Default);
        if (i < 0) {
            i = ~i;
            this.Directories.Insert(i, dn);
        }
        String[] newPath = new String[path.Length - 1];
        Array.Copy(path, 1, newPath, 0, newPath.Length);
        this.Directories[i].AddPath(newPath, index,fileIndex);
        return;
    }
    else if (path.Length == 1) //a file!
    {
        DirNode fn = new DirNode(path[0], index, 1, fileIndex);
        int i = this.Directories.BinarySearch(fn, DirNodeNameComparer.Default);
        this.Directories.Insert(~i, fn); // really Directories?
        return;
    }
    else
    {
        //really no reason why we should be here. 
        return;
    }
}