AJM
AJM

Reputation: 32490

Multidimensional Data Structure in C#

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 :-(

Upvotes: 1

Views: 6917

Answers (6)

Steve Cooper
Steve Cooper

Reputation: 21470

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.

Upvotes: 3

Henk Holterman
Henk Holterman

Reputation: 273179

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.

Upvotes: 2

TheTXI
TheTXI

Reputation: 37875

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)

Upvotes: 5

Colin Burnett
Colin Burnett

Reputation: 11518

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).

Upvotes: 2

Tomas Aschan
Tomas Aschan

Reputation: 60564

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.

Upvotes: 3

Kane
Kane

Reputation: 16802

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

Upvotes: 3

Related Questions