Проблема со списком списков C #

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

}