Основное дерево папок со списком строк


Я строю базовую дерево папок со списком строк в форме /корень/узел/узел/Узел. Вот основной алгоритм я использую в настоящее время, чтобы построить этот сбор и заполнить TreeGridView:

// This method gets the list of folders and leaves, then trims out any folder paths
// that are already encompassed in a larger folder path, the idea is that it causes
// less work when adding the actual tree nodes (I may be wrong in this assumption)
List<string> BuildFinalList()
{
    // This list is a collection of root folder paths and leaf folder names
    // i.e. pair("/root/node/node", "node"), pair("/root/node", "node)
    List<KeyValuePair<string, string>> folders = GetListOfFolders();
    var paths = new List<string>();
    foreach(var folder in folders)
    {
        var leaf = folder.Value;
        var root = folder.Key;
        paths.Add(string.Concat(root, "/", leaf);
    }
    paths.Sort(_INVERSE_LENGTH_COMPARE); // this sorts the list longest to shortest

    // Iterate the computed paths from longest to shortest, if a path is not
    // encompassed by an existing path in the final list, add it to the
    // final list, otherwise just move to the next path
    var finalList = new List<string>();
    foreach(var path in paths)
    {
        bool found = false;
        foreach(var item in finalList)
        {
            if (item.StartsWith(path, StringComparison.Ordinal))
            {
                found = true;
                break;
            }
        }

        if (!found)
        {
            finalList.Add(path);
        }
    }
    return finalList;
 }

Как только я получу окончательный список причине, то я могу добавить узлы к дереву (для упрощения, я удалил призывов к прекращению обновления и начать обновление дерева, которое содержит корневой узел):

void FillTreeNodes(TreeNode root)
{
    var rootText = root.Text;
    var rootTextLength = rootText.Length;
    var nodeStrings = BuildFinalList();
    foreach(var nodeString in nodeStrings)
    {
        var roots = nodeString.Split(new char[] { '/' },
            StringSplitOptions.RemoveEmptyEntries);

        // The initial parent is the root node
        var parentNode = root;
        var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength);
        for(int rootIndex = 0; rootIndex < roots.Length; rootIndex++)
        {
            // Build the node name
            var parentName = roots[rootIndex];
            sb.Append("/");
            sb.Append(parentName);
            var nodeName = sb.ToString();

            // Search for the node
            var index = parentNode.Nodes.IndexOfKey(nodeName);
            if (index == -1)
            {
                 // Node was not found, add it
                 var temp = new TreeNode(parentName, 1, 1);
                 temp.Name = nodeName;
                 parentNode.Nodes.Add(temp);
                 parentNode = temp;
            }
            else
            {
                 // Node was found, set that as parent and continue
                 parentNode = parentNode.Nodes[index];
            }
        }
    }
}


5957
7
задан 9 февраля 2011 в 03:02 Источник Поделиться
Комментарии
1 ответ

Одно усовершенствование, которое приходит на ум, это:

bool found = false;
foreach(var item in finalList)
{
if (item.StartsWith(path, StringComparison.Ordinal))
{
found = true;
break;
}
}

Выяснить, является ли условие выполняется для любого элемента в коллекции-это достаточно распространенная проблема, что для LINQ метод для этого: перечисли.Любой. Используя приведенный выше код может быть записан как просто:

bool found = finalList.Any(item =>
item.StartsWith(path,StringComparison.Ordinal);

Который является одновременно короче и проще.

5
ответ дан 9 февраля 2011 в 04:02 Источник Поделиться