#c# #arrays #list
#c# #массивы #Список
Вопрос:
У меня есть еще один вопрос со списком списков. Еще раз, у меня есть общий класс matrix, как показано ниже.
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 });
matrix.Add(new List<double>() { 16.0, 4.0 });
Я читаю строки строк из текстового файла, который содержит значения в следующем формате,
4 2
0.5 0.4 0.6 0.1 10.1 11.1 0.5 12.0
В первой строке указывается размер матрицы 4×2. Вторая строка должна быть такой, чтобы первые 4 значения находились в первом столбце матрицы, а последние четыре значения должны быть во втором столбце. Это динамическое, поэтому размер не фиксирован.
Сортируется чтение строк и разделение этих строк. Мой вопрос заключается в том, как использовать класс Matrix для хранения этих значений. Другими словами, как я могу сделать элементы в строке?
Это должно быть сделано так, чтобы матрица выглядела как,
0.5 10.1
0.4 11.1
0.6 0.5
0.1 12.0
Заранее спасибо.
Комментарии:
1. В чем проблема с кодом, который у вас уже есть? Похоже, это должно сработать?
2. Вопрос заключается в добавлении части. Поскольку это динамично, я не знаю, как я могу достичь matrix.Add(new List<double>() { элементы строки })
3. Вы уже делаете это в коде — вы хотите добавить несколько строк одновременно?
4. действительно. это мой вопрос. извините, я неправильно сформулировал это.
Ответ №1:
Должны ли ваши размеры матрицы действительно быть изменяемыми? Лучшей альтернативой может быть передача его измерений внутри конструктора и выделение массивов внутри матрицы:
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; }
}
}
В качестве альтернативы, если он должен быть изменяемым, вы можете выбрать его «ленивым», по мере необходимости:
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));
}
}
Обратите внимание, что второй подход может выполнять много распределений, если вы заполняете его последовательно.
Я бы выбрал первый подход (матрица фиксированного размера), поскольку в большинстве случаев ее размеры уже известны. Его быстрее всего распределять, и его безопасно использовать в многопоточном приложении.
Если вы считываете значения из файла, установка их с помощью индексов должна быть намного проще, чем создание нового списка для каждой строки.
Комментарии:
1. @kuzyt: Я забыл добавить
set
средства доступа в моей первой редакции. Я обновил его.
Ответ №2:
public void AddRange(IEnumerable<List<T>> rows)
{
foreach (var row in rows)
{
Add(row);
}
}
Затем:
AddRange(new List<double>[] {
new List<double> { 0.0, 0.0 },
new List<double> { 16.0, 14.0 } });
Комментарии:
1. похоже, вы, возможно, неправильно поняли мой вопрос, потому что я неправильно его сформулировал. Проблема в том, что я не знаю, что находится в текстовом файле, который читается. следовательно, размер матрицы является динамическим.
2. Вы не спрашивали о чтении файлов, вы спрашивали о списках списков и о том, как добавить их в свою матрицу .. решение, которое вы дали, и я расширил, касается матриц любого размера, нерегулярных, если это необходимо .. другой ответ, тоже не касается чтения ..?
Ответ №3:
Итак, вам нужен ctor, который принимает 2 параметра, ширину и значения.
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;
}
}