【问题标题】:What kind of data structure to use?使用什么样的数据结构?
【发布时间】:2012-06-01 19:49:20
【问题描述】:

我正在做一个需要跟踪的项目:

  • 5-6 根项目只是一个字符串名称
  • 每个根项都需要有多个不同标识符类型(int、string、float 等)的子项。一个根的所有子节点都是同一类型,但每个根节点都有不同的子节点类型
  • 用户需要能够从每个根目录添加/删除子节点
  • 稍后我需要单独访问每个孩子,并在需要时执行字符串操作和解析

我考虑过使用字典,其中键是字符串,值是对象列表。或者为每个根项设置一个唯一的类,并且每个类都包含一个子列表。

有人有什么好的建议吗?我对 OOP 还是很陌生,请多多包涵:)

谢谢!

【问题讨论】:

  • 乍一看,Dictionary> 看起来就像你要找的东西。
  • 你想强制给定根的所有子节点都是同一类型吗?我正在努力寻找一种方法来做到这一点。如果您愿意在没有那种级别的类型强制的情况下生活,Dictionary<string, List<object>> 会起作用。
  • 给定根的子节点不必是相同的类型,事实上,如果它们不是相同的类型可能会更好。所以使用元组,我将能够动态添加/删除我想要的任何类型的项目?
  • 我的第一眼感觉不对 - jonnyGold 的解决方案既快速又优雅。

标签: c# oop data-structures


【解决方案1】:
public interface IRoot {}

public class RootItem<T> : IRoot
{
    public string Name { get; set; }
    public List<T> Children {get; set; }
}

然后保留一个Dictionary&lt;string, IRoot&gt; 来保存它们。

Dictionary<string, IRoot> hair = new Dictionary<string, IRoot>();
hair.Add(
  new RootItem<int>()
      {
        Name = "None",
        Children = new List<int>() {1, 2, 3, 4}
      }
);

hair.Add(
  new RootItem<decimal>()
      {
        Name = "None",
        Children = new List<decimal>() {1m, 2m, 3m, 4m}
      }
);

【讨论】:

  • 谢谢。作为记录,@FishBasketGordo 提供了一个更加充实的样本。
  • Dictionary&lt;string, RootItem&gt; 无效,因为没有泛型参数的 RootItem 是不完整的类型。
  • 好点。我错过了。我使用 Visual Studio 编写这些代码示例。
  • 还是不太对……你不能构造一个Dictionary&lt;string, RootItem&lt;T&gt;&gt;——你必须给它一个具体的类型,然后所有或你的子列表现在都是相同的类型。
  • 但是现在,你只能拥有一种 T 类型的孩子。
【解决方案2】:

List&lt;T&gt; 来包含孩子的泛型类怎么样:

public class Root<T>
{
    private List<T> children = null;

    public Root(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    public List<T> Children
    {
        get
        {
            if (children == null)
            {
                children = new List<T>();
            }

            return children;
        }
    }
}

Root<int> intRoot = new Root<int>("IntRoot");
intRoot.Children.Add(23);
intRoot.Children.Add(42);

Root<string> stringRoot = new Root<string>("StringRoot");
stringRoot.Children.Add("String1");
stringRoot.Children.Add("String2");
stringRoot.Children.Add("String3");
stringRoot.Children.Add("String4");

如果你想在一个对象中保存所有的根,你可以编写自己的类或使用Tuple

var rootGroup = Tuple.Create(intRoot, stringRoot);
// intRoot is accessible as rootGroup.Item1
// stringRoot is accessible as rootGroup.Item2

【讨论】:

  • 这是我想出的,但 OP 还想要一个 Dictionary&lt;string, RootItem&gt;,我认为这是不可能的;你可以有一个基本的非泛型 RootItem 类,但你会在这个过程中失去一些类型安全......
  • 对不起,我缺乏编程知识!所以当你声明 intRoot 和 stringRoot 时,在等号的右边,你基本上是在调用 Root(string name) 函数吗?或者..你的类中的 Root(string name)“东西”是否被认为是构造函数?
  • 它是一个构造函数。任何时候你看到new 操作符,你都在处理一个构造函数。此外,您可以通过查看类本身来判断它是构造函数,因为它与类命名相同并且没有显式返回类型。
【解决方案3】:

听起来Dictionary&lt;string, Tuple&lt;type1, type 2, etc&gt;&gt; 是一个不错的候选者。

键将是字符串(根)。根的孩子是一个元组。我们可以向元组添加项目。感谢您指出这一点。

Good starting point on Tuple

【讨论】:

  • 您不能在运行时从元组中添加或删除项目。
  • Tuple&lt;T1, T2, ...&gt; 构造允许异构的Dictionary 值,但@swifferclean 提到每个值将是一个任意列表,其中每个项目都是相同类型的。它需要改变的值列表的类型。
  • 嗯..我明白了。所以使用 List 可能会更好?我认为您可以在运行时从列表中添加和删除项目,对吧..?
【解决方案4】:

这是解决问题的一种方法。有很多演员需要进行,但它可以完成工作:

    static void Main(string[] args)
    {
        Dictionary<string, IRootCollection> values = new Dictionary<string, IRootCollection>();

        values["strings"] = new RootCollection<string>();
        (values["strings"] as RootCollection<string>).Add("foo");
        (values["strings"] as RootCollection<string>).Add("bar");

        values["ints"] = new RootCollection<int>();
        (values["ints"] as RootCollection<int>).Add(45);
        (values["ints"] as RootCollection<int>).Add(86);
    }

    interface IRootCollection { }
    class RootCollection<T> : List<T>, IRootCollection { }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2021-02-26
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多