I've got another question with List of lists. Once again, I have the generic matrix class as below.
public class Matrix<T>
{
List<List<T>> matrix;
public Matrix()
{
matrix = new List<List<T>>();
}
public void Add(IEnumerable<T> row)
{
List<T> newRow = new List<T>(row);
matrix.Add(newRow);
}
}
// Test code
Matrix<double> matrix = new Matrix<double>();
matrix.Add(new List<double>() { 0, 0 });开发者_Go百科
matrix.Add(new List<double>() { 16.0, 4.0 });
I'm reading lines of strings from a text file which contains values with the following format,
4 2
0.5 0.4 0.6 0.1 10.1 11.1 0.5 12.0
The first line specifies the 4x2 matrix size. The second line needs to be so that first 4 values are in the first column of the matrix and the last four values should be in the second column. This is dynamic hence the size is not fixed.
Reading the lines and delimiting these lines is sorted. My question is around how to use the Matrix class to store these values. In other words how can I do the elements in a row ?
It should be done so that the matrix will look like,
0.5 10.1
0.4 11.1
0.6 0.5
0.1 12.0
Thanks in advance.
Should your matrix dimensions really be mutable? A better alternative might be to pass its dimensions inside constructor and allocate arrays inside the matrix:
public class Matrix<T>
{
private readonly T[][] _matrix;
public Matrix(int rows, int cols)
{
_matrix = new T[rows][];
for (int r = 0; r < rows; r++)
_matrix[r] = new T[cols];
}
public T this[int r, int c]
{
get { return _matrix[r][c]; }
set { _matrix[r][c] = value; }
}
}
Alternatively, it it does need to be mutable, you can choose to allocate it "lazy", as needed:
public class Matrix<T>
{
private readonly List<List<T>> _matrix;
public Matrix()
{
_matrix = new List<List<T>>();
}
public T this[int r, int c]
{
get
{
ResizeIfNeeded(r, c);
return _matrix[r][c];
}
set
{
ResizeIfNeeded(r, c);
_matrix[r][c] = value;
}
}
private void ResizeIfNeeded(int row, int col)
{
while (_matrix.Count <= r)
_matrix.Add(new List<T>());
var row = _matrix[r];
while (row.Count <= c)
row.Add(default(T));
}
}
Note that the second approach might do a lot of allocations if you are populating it sequentially.
I would opt for the first approach (a fixed size matrix), since in most cases its dimensions are already known. It is fastest to allocate, and it's safe to use in a multithreaded application.
If you are reading values from a file, setting them through indices should much simpler than instantiating a new list for each row.
public void AddRange(IEnumerable<List<T>> rows)
{
foreach (var row in rows)
{
Add(row);
}
}
Then:
AddRange(new List<double>[] {
new List<double> { 0.0, 0.0 },
new List<double> { 16.0, 14.0 } });
So wou want a ctor that takes 2 parameters, width and values.
public Matrix(int width, IEnumerable<T> values)
{
if (values.Count() % width != 0)
throw new ArgumentException("values parameter is indivisible by width");
int last = 0;
for (int i = width; i <= values.Count(); i += width)
{
Add(values.Skip(last).Take(width))
last = i;
}
}
精彩评论