【问题标题】:Three layer deep malleable strings三层深延展弦
【发布时间】:2011-08-30 02:20:55
【问题描述】:

我正在尝试实现三层深层数据结构。这很容易做到,直到您添加能够在孩子和/或田地周围移动的要求,然后它变成了一场噩梦。

父(索引,ID)-> 子(索引)-> 字段(索引,字符串)

例如,数据可能如下所示:

  • 块 1(“块 1”)
    • 孩子1
      • 字段1(“你好”)
      • Field2(“世界”)
    • 孩子2
      • 字段1(“一”)
      • 字段2(“二”)
      • Field3(“三”)
  • Block2(“Block2”)
    • 孩子1

现在我可以通过为 Parent 和 Field 创建一个包含 ArrayList 和 String 的结构来实现这一点,而对于 Children 则只包含一个 Arraylist,但是当我需要例如反转 Field1 和 Field2 时,它变得既困难又昂贵。

这整个事情在像 C++ 这样的语言中似乎很容易,因为我可以将所有字段转储到一个巨大的数据块中,然后使用指针来引用字段的位置......然后如果我想切换字段,孩子,或者父母,我只要改变指针,它就很便宜。

以前有人在 C# 中见过这种数据模式吗?是否有“标准”方式来实现这一点?

【问题讨论】:

  • 为什么你不能这样做,但使用引用而不是指针?

标签: c#


【解决方案1】:

不要使用结构,使用类。这些操作只是昂贵的,因为使用结构需要您复制数据,而您可能只是复制对象引用。您对结构的使用可能是由于您使用 C++ 的经验;在 C# 中,您想要使用它们的场合较少。

当您在 C# 中实例化您的对象时,您“将所有字段转储到一个巨大的数据块中,然后使用指针来引用字段所在的位置”。这就是new 运算符所做的事情:它在堆上分配对象并为您提供指向它们的指针。没有必要明确地实现这样的事情。

在 C# 中显式地微观管理内存是很困难的,但如果你停止尝试这样做,那么我认为你会发现你的生活变得更加轻松。如果你真的想管理内存,请回到 C++。

【讨论】:

    【解决方案2】:

    为什么不简单地将其组织为对象层次结构?

    public class Block
    {
         public List<Child> Children { get; set; }
         public string Name { get; set; }
    }
    
    public class Child
    {
         public List<Field> Fields { get; set; }
    }
    
    public class Field
    {
         public List<string> FieldNames { get; set; }
    }
    

    然后,您只需向列表添加一个新引用,或者如果您需要重新排列内容,您可以简单地修剪引用或对列表进行不同的排序。我错过了什么吗?

    【讨论】:

      【解决方案3】:

      交换两个引用实际上会很便宜,而且实际上即使您想从一个孩子身上移除一个项目并将其添加到另一个孩子,它仍然几乎总是足够便宜。

      using System.Collections.Generic;
      
      public class Block : List<Child> {
          public int ID { get; set; }
      
          public Block(int id) {
              this.ID = id;
          }
      }
      
      public class Child : List<string> {
      
      }
      
      public class Test {
          public static void Main() {
              List<Block> blocks = new List<Block>() {
                  new Block(1) {
                      new Child() {
                          "Hello",
                          "World"
                      },
                      new Child() {
                          "One",
                          "Two",
                          "Three"
                      }
                  },
                  new Block(2) {
                      new Child()
                  }
              };
      
              string temp = blocks[0][0][0];
              blocks[0][0][0] = blocks[0][0][1];
              blocks[0][0][1] = temp;
          }
      }
      

      【讨论】:

        【解决方案4】:

        在管理字段方面没有发现任何问题。将它们推送到列表中,并且在您想要更改序列时,只需交换该列表中的对象。如果从性能角度来看这很昂贵,那么您可以使用 Dictionary 与键(如字段索引和值字段本身)而不是列表,并且在需要的情况下只需交换整数。

        【讨论】:

          猜你喜欢
          • 2010-10-13
          • 1970-01-01
          • 2021-07-04
          • 1970-01-01
          • 1970-01-01
          • 2021-12-20
          • 2015-12-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多