tags:

views:

49

answers:

2

Hello,

I have a function that checks whether a string represents a filesystemlocation beneath another string. My question however should be applicable to any function returning boolean.

Here is the function anyway...

private bool IsItemBelowPath(string item, string path)
{

    if (path == Path.GetPathRoot(path))
    {
        path = path.TrimEnd('\\');
    }

    if (item.Length < path.Length + 2)
        return false;

    return (string.Compare(item, 0, path, 0, path.Length, StringComparison.OrdinalIgnoreCase) == 0 &&
        item[path.Length] == Path.DirectorySeparatorChar);

}

I have a List that contains file and folder paths that I like to filter (with above function) so that no nesting occur.

These paths

  • C:\Path
  • C:\Path\SubPath
  • C:\Path\File.txt
  • D:\
  • D:\Path
  • D:\File.txt

Should become

  • C:\Path
  • D:\

I need to compare all paths with all other ones and return the correct ones.

I'm quite new to development but suspect that a LINQ statement, using the function above, could accomplish this, i've tried the following but it gives wrong result

var items = new List<string> { my paths.... } 

return (from i1 in items
        from i2 in items
        where !IsItemBelowPath(i1, i2)
        select i2).Distinct().ToList();

Thanks for any help.

+2  A: 

An alternative approach that is easier to read, has better performance, and gives the correct result is to iterate over the items and use Any to test if any of the other items are a sub-path of that item:

var query = items
    .Where(i1 => !items.Any(i2 => IsItemBelowPath(i1, i2)))
    .ToList();

Result:

C:\Path
D:\
Mark Byers
Thanks looks like your example is working
risc
A: 

Try:

return (from item in items
        where items.Any(parent => IsItemBelowPath(parent,item))
        select item);

In your code you're considering every pair, and there's bound to be at least one where one is not a sub-path of the other.

mancaus
I like this as it's more readable than the one above but it misses items that doesn't have children. Add @"E:\Path" to my paths above to test.
risc