1

I want to build a data structure which is basically a matrix of strings with the following.

  1. A growable no of rows
  2. A FIXED no of columns

I want to be able to get at whatever is in a particular row or column via a method call that takes the an integer row no and an int col number as an argument. In addition I want to be able to set the value of a column which using the row and col no.

I could do this myself but am open to seeing what other people might do...

EDIT Sorry the column list will be fixed, my mistake :-(

4

6 回答 6

5

The DataTable and the DataSet (basically a collection of data tables) would work fine for what you are looking for.

You could then access your data (once you set up the columns and added your rows of data) via the following syntax:

datatable.rows(index)("ColumnName")

or

datatable.rows(rowindex)(columnindex)
于 2009-06-08T19:09:14.823 回答
3

Sounds to me like a data table would be the easiest opion.

于 2009-06-08T19:07:04.967 回答
3

How about basing something on Dictionary<System.Drawing.Point, string>? So that you can write;

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

Create a class containing such a dictionary and then you get what you're looking for, almost for free. Something like (untested)

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

EDIT: Also, if you want to get really flash;

  • replace the dictionary with a SortedList<,>
  • replace System.Drawing.Point with your own struct which implements IComparable

This way, the list would be internally ordered by row, then by column, making a simple foreach loop sufficient to iterate through all the values in the first row, then the values in the second, and so on. Allows you to convert to and `IEnumerable`` -- or a collection of rows.

于 2009-06-08T19:11:17.033 回答
3

If you need more than two dimensions, or want a more generic solution, you could possibly make it work with a List<List<T>>, nested as deeply as required, and wrapped in a custom type if you need more specific functionality or want simpler method calls.

于 2009-06-08T19:12:30.573 回答
2

If I wanted/needed to roll my own (say I didn't want to deal with what DataTable/DataSet) then I'd write something around a List<List<T>> (or List<List<object>>) as a list of rows then columns with logic to keep the lists rectangular.

  • AddRow() would add a new outer list entry.
  • AddColumn() would add a new item to all lists in the inner list.
  • this[int row, int col] would access this._Data[row][col].

Something like that.

Switch to a Dictionary<K, List<V>> if I wanted named columns (then the lists contain row data for that column).

于 2009-06-08T19:12:48.497 回答
2

If you want it to be expandable in both directions then a DataTable isn't the best of choices.

For the interface, you can use an indexer property:

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

For the backend Storage, the best option depends a bit on expected usage, ie will there be lots of empty cells. You could define a

struct Index { public readonly int X, Y; }

and override the Equals() and GetHashCode() members. There have been several questions about this on SO recently.

After that, use a Dictionary < Index, string>

You'd still have to manage Row and Column limits, and maybe intercept getting of empty cells.

于 2009-06-08T19:18:39.127 回答