Question

I am trying to extract from a series of strings which represents depth like:

'foo/bar/x'
'foo/bar/baz/x'
'foo/bar/baz/x'
'foo/bar/lol/x'

Where x is a number I don't care about. I've got as far as splitting on the / and looping through, at which point in PHP I'd do something like check where in the loop I am (using for (i=0; etc)) and then use that to determine my depth to build an output array like:

output['foo']['bar'] = 1
output['foo']['bar']['baz'] = 2
output['foo']['bar']['lol'] = 1

The trouble is the 'depth' is dynamic and might be either just 3/4 deep (which I could just account for with lots of checks on the value of i and handling them separately) or say 10 or more deep in which case some kind of recursive function is probably best.

I've come across the issue that to have a string as an array index I need to use a dictionary, but you have to specify the types in the dictionary, meaning you need to know the depth in advanced (correct me if I'm wrong) when instantiating a dictionary object.

I guess an attack might be something like calling a recursive function such that each time it's called you pass i to indicate the depth, then the function calls itself decrementing i each time until it has built the portion of the tree from that input string but it's what storage structures I use for that in C# that I am not sure about.

The final output will be a CSV that I can open as a spreadsheet to look like:

Foo        0
|__Bar     1
   |__Baz  2
   |__Lol  1

Perhaps one direction for a solution is to use a pure C# Array and simply store the title (e.g. foo) in there, keeping information out of array indicies, which is probably best practice anyway. Thanks.

Was it helpful?

Solution

You can create your own class with following members:

class Directory
{
    public int Value { get; set; }
    public Dictionary<string, Directory> SubDirectories { get; set; }
}

Store your data using it and then recursively export it to CSV.

To get output["foo"]["bar"] syntax possible implement indexer within your class:

public Directory this[string name]
{
    get { return SubDirectories.ContainsKey("name") ? SubDirectories[key] : null; }
    set { SubDirectories.Add(name, value); }
}

OTHER TIPS

While Marcin Juraszek solution is great, I just want to expand his answer just a little bit with dynamic sugar. It's not the fact, that this solution will fit your need, but just consider it as an example. I will make Directory<T> generic, so you can use whatever type for value (note that due to dynamic nature I have one cast in implementation (T)value)

class Directory<T> : DynamicObject
{
    private T Value;
    private Dictionary<string, Directory<T>> SubDirectories;

    public Directory()
    {
        SubDirectories = new Dictionary<string, Directory<T>>();
    }

    public override bool TryGetMember(GetMemberBinder binder, out Object result)
    {
        if (!SubDirectories.ContainsKey(binder.Name))
            SubDirectories[binder.Name] = new Directory<T>();

        result = SubDirectories[binder.Name];   
        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, Object value)
    {
        if (!SubDirectories.ContainsKey(binder.Name))
            SubDirectories[binder.Name] = new Directory<T>();

        SubDirectories[binder.Name].Value = (T)value;
        return true;
    }

    public override string ToString()
    {
        return Value.ToString();
    }
} 

And now you can use dynamic feature, available from C# 4.0

dynamic dir = new Directory<string>();

dir.foo = "Foo Value";
dir.foo.bar = "Bar Value";
dir.foo.bar.baz = "baz value";
dir.foo.bar.Lol = "Lol value";

Console.WriteLine(dir.foo.bar.Lol); //will print Lol value
Console.WriteLine(dir.foo.bar.baz); //will print baz value

which is:

Foo        Foo Value
|__Bar     Bar Value
   |__Baz  baz value
   |__Lol  Lol value

you can also override TryGetIndex and TrySetIndex so that you can pass complex strings, which can't be used as properties in C#

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top