【问题标题】:Multidimensional Data Structure in C#C# 中的多维数据结构
【发布时间】:2010-11-01 06:30:48
【问题描述】:

我想构建一个数据结构,它基本上是一个字符串矩阵,具有以下内容。

  1. 可增长的行数
  2. 固定的列数

我希望能够通过将整数行号和 int col 号作为参数的方法调用来获取特定行或列中的任何内容。另外我希望能够设置使用行和列号的列的值。

我可以自己做,但我愿意看看其他人可能会做什么......

编辑抱歉,列列表将被修复,我的错误:-(

【问题讨论】:

  • 很好的问题,但您能否画一张图片来添加一些上下文,例如(预期)大小、可以添加行/列的频率等。
  • 列将被修复。它将是 UI 组件的后端,用户可以在其中添加新记录,因此可以相当频繁地添加行。不处理大量数据(少于 20 条记录)
  • 编辑(固定列)将其翻转过来。数据表会更好。但没那么有趣。
  • 到目前为止你尝试了什么?

标签: .net data-structures multidimensional-array


【解决方案1】:

基于Dictionary<System.Drawing.Point, string> 的东西怎么样?这样你就可以写了;

stringGrid.Add(new Point(3,4), "Hello, World!");

创建一个包含这样一个字典的类,然后你就可以得到你要找的东西,几乎是免费的。类似(未经测试)

class StringGrid
{
    Dictionary<System.Drawing.Point, string> grid;

    public StringGrid
    {
        this.grid = new Dictionary<System.Drawing.Point, string>();
    }

    public string Get(int x, int y)
    {
        string result = null;
        grid.TryGetValue(new Point(x,y), out result);
        return result;
    }

    public void Set(int x, int y, string content)
    {
        var pos = new Point(x,y);
        if (grid.ContainsKey(pos))
        {
            if (content == null)
            {
                // no content, so just clear the cell.
                grid.remove(pos);
            }
            else
            {
                // add new content
                grid[pos].Value = content;
            }  
        } 
        else if (content != null)
        {
            // new non-null content
            grid.add(pos, content);
        }
    }
}

编辑:另外,如果你想获得真正的闪光;

  • 将字典替换为SortedList&lt;,&gt;
  • 用你自己的实现IComparable的结构替换System.Drawing.Point

这样,列表将在内部按行排序,然后按列排序,使一个简单的foreach 循环足以遍历第一行中的所有值,然后是第二行中的值,依此类推。允许您转换为和 `IEnumerable` -- 或行的集合。

【讨论】:

  • 两件事:1) 使用索引器 :) 和 2) 点字典不会使矩阵保持矩形。我假设 #2 很重要。
  • 这确实不错。并且很容易为它推出自己的索引器。不过,矩形的东西......我想你可以在添加列或行时保持“对齐”,但这会有点工作。如果允许锯齿状,则更容易。
  • 或多或少也是我的想法,但我宁愿不为此使用 Drawing.Point。实在是太离谱了。但从技术上讲,它是可以使用的。
  • Drawing.Point -- 是的,创建自己的结构可能会更好(它必须是结构,否则字典将不起作用),但它与 Drawing.Point 完全相同。矩形矩阵——这将无限增长,作为一个纯稀疏矩阵。它不需要担心它。如果需要的话,它确实需要 O(n) 操作来找到边界框尺寸,但没有说明。
  • @Steve,您当然可以使用字典中的对象作为键。您需要实现 Equals 和 GetHashCode、IEquatable,或者为 Dictionary 构造函数指定一个 IEqualityComparer
【解决方案2】:

如果您希望它可以双向扩展,那么 DataTable 不是最佳选择。

对于接口,您可以使用索引器属性:

class Foo 
{   
    public string this[int x, int y]
    {
        get { return GetData(x,y); }
    }
}

对于后端存储,最好的选择取决于预期的使用情况,即会有很多空单元格。你可以定义一个

struct Index { public readonly int X, Y; }

并覆盖 Equals() 和 GetHashCode() 成员。最近在 SO 上有几个关于这个的问题。

之后,使用Dictionary &lt; Index, string&gt;

您仍然必须管理行和列限制,并且可能会拦截空单元格的获取。

【讨论】:

    【解决方案3】:

    DataTable 和 DataSet(基本上是数据表的集合)可以很好地满足您的需求。

    然后您可以通过以下语法访问您的数据(一旦您设置了列并添加了数据行):

    datatable.rows(index)("ColumnName")
    

    datatable.rows(rowindex)(columnindex)
    

    【讨论】:

      【解决方案4】:

      如果我想要/需要自己推出(比如我不想处理 DataTable/DataSet),那么我会在 List&lt;List&lt;T&gt;&gt;(或 List&lt;List&lt;object&gt;&gt;)周围写一些东西作为行列表,然后是具有逻辑的列,以保持列表为矩形。

      • AddRow() 将添加一个新的外部列表条目。
      • AddColumn() 将向内部列表中的所有列表添加一个新项目。
      • this[int row, int col] 将访问 this._Data[row][col]

      类似的东西。

      如果我想要命名列(然后列表包含该列的行数据),请切换到 Dictionary&lt;K, List&lt;V&gt;&gt;

      【讨论】:

        【解决方案5】:

        如果您需要两个以上的维度,或者想要一个更通用的解决方案,您可以使用 List&lt;List&lt;T&gt;&gt;,根据需要尽可能深地嵌套,如果您需要更具体的功能或想要包装在自定义类型中更简单的方法调用。

        【讨论】:

        • 如果他们有密钥或 ID,您可能希望使用 SortedList> 来加快访问速度。
        【解决方案6】:

        在我看来,数据表是最简单的选择。

        【讨论】:

          猜你喜欢
          • 2010-10-14
          • 2014-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多