2

我正在尝试从一系列代表深度的字符串中提取,例如:

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

x我不关心的数字在哪里。我已经完成了拆分/和循环,此时在PHP中我会做一些事情,比如检查我在循环中的位置(使用for (i=0; etc)),然后用它来确定我的深度来构建一个输出数组,如:

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

问题是“深度”是动态的,可能只有 3/4 深(我可以通过对它们的值进行大量检查i并单独处理它们来解释)或者说 10 或更深,在这种情况下某种递归函数可能是最好的。

我遇到了将字符串作为数组索引的问题,我需要使用字典,但您必须指定字典中的类型,这意味着您需要了解高级的深度(如果我是,请纠正我错误)在实例化字典对象时。

我猜攻击可能类似于调用递归函数,这样每次调用它时你传递i指示深度,然后函数调用自身i每次递减,直到它从输入字符串构建树的一部分,但它是什么存储我在 C# 中使用的我不确定的结构。

最终输出将是一个 CSV,我可以将其作为电子表格打开,如下所示:

Foo        0
|__Bar     1
   |__Baz  2
   |__Lol  1

也许解决方案的一个方向是使用纯 C# 数组并简单地将标题(例如foo)存储在其中,将信息保留在数组索引之外,无论如何这可能是最佳实践。谢谢。

4

2 回答 2

5

您可以使用以下成员创建自己的类:

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

使用它存储您的数据,然后递归地将其导出为 CSV。

要获得output["foo"]["bar"]可能的语法,请在您的类中实现索引器:

public Directory this[string name]
{
    get { return SubDirectories.ContainsKey("name") ? SubDirectories[key] : null; }
    set { SubDirectories.Add(name, value); }
}
于 2013-04-02T12:02:58.533 回答
2

虽然 Marcin Juraszek 的解决方案很棒,但我只想用dynamic糖来扩展他的答案。事实并非如此,该解决方案将满足您的需求,而只是将其视为示例。我将Directory<T>通用,因此您可以使用任何类型value(请注意,由于动态性质,我在实现中有一个演员(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();
    }
} 

现在您可以使用C# 4.0dynamic中提供的功能

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

这是:

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

您还可以覆盖TryGetIndexTrySetIndex以便您可以传递复杂的字符串,这些字符串不能用作 C# 中的属性

于 2013-04-02T12:41:11.617 回答