HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Basic folder tree with a list of strings

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withbasicfolderliststringstree

Problem

I am building up a basic folder tree with a list of strings in the form /root/node/node/node. Here is the basic algorithm I am using currently to build this collection and fill in my 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 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> folders = GetListOfFolders();
    var paths = new List();
    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();
    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;
 }


Once I have the final list built, I then add the nodes to the tree (for simplification, I have removed the calls to end update and begin update of the tree that contains the root node):

```
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[] { '/' }

Solution

One improvement that comes to mind is:

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


Finding out whether a condition is met for any item in a collection is a common enough problem that LINQ has a method for that: Enumerable.Any. Using that the above code can be written as just:

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


Which is both shorter and simpler.

Code Snippets

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

Context

StackExchange Code Review Q#707, answer score: 6

Revisions (0)

No revisions yet.