Domanda

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.

È stato utile?

Soluzione

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); }
}

Altri suggerimenti

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#

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top