Reputation: 32490
I want to build a data structure which is basically a matrix of strings with the following.
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
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;
SortedList<,>
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
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
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
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
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