Как прочитать 2d текстовый файл в 2d массив с помощью PLinq

У меня есть файл.txt, как это:

1,2,3,4,5  
6,7,8,9,10  
11,12,13,14,15  
16,17,18,19,20

Я хочу прочитать этот файл в двойной массив с PLinq с этим кодом:

        OpenFileDialog ofd = new OpenFileDialog();
        ofd.Filter = "Text Files(*.txt)|*.txt";
        if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            number_of_users = File.ReadAllLines(ofd.FileName).Length;
            number_of_services = File.ReadAllLines(ofd.FileName)[0].Split(',').Length;    
            quality_of_service_array = new double[number_of_users, number_of_services]; 
            quality_of_service_array = File.ReadAllLines(ofd.FileName)
               .Select(l => l.Split(',').Select(i => double.Parse(i)).ToArray())
               .ToArray();
}

Этот массив должен иметь 4 строки и 5 столбцов.
Но я получаю эту ошибку:

Невозможно неявно преобразовать тип 'double[][]' в 'double [,].

Я знаю значение этой ошибки, но я не эксперт в PLinq.

2 ответа

Решение

Вы не используете PLINQ, Также нет простого способа вернуть 2d-массив из запроса LINQ. Если вы настаиваете на LINQ, вы можете использовать этот метод для его преобразования:

public T[,] JaggedToMultidimensional<T>(T[][] jaggedArray)
{
    int rows = jaggedArray.Length;
    int cols = jaggedArray.Max(subArray => subArray.Length);
    T[,] array = new T[rows, cols];
    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            array[i, j] = jaggedArray[i][j];
        }
    }
    return array;
}

Тогда все просто (б AsParallel потому что вы упомянули PLINQ):

double[][] quality_of_service_array = File.ReadLines(ofd.FileName).AsParallel()
    .Select(l => Array.ConvertAll(l.Split(','), double.Parse))
    .ToArray();
double[,] qos_2d = JaggedToMultidimensional(quality_of_service_array);

Это предполагает, что формат в текстовом файле всегда правильный, в противном случае вы получите исключение в double.Parse, Вы могли бы использовать double.TryParse проверить это.

Вы можете преобразовать зубчатый массив в двумерный массив, как показал Тим Шмельтер.

В вашем примере вы без необходимости читаете один и тот же файл снова и снова, и эта вещь на самом деле не имеет ничего общего с PLINQ. Вы можете прочитать файл один раз в массив. то есть:

OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Text Files(*.txt)|*.txt";
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
  var quality_of_service_array = File.ReadAllLines(ofd.FileName)
     .Select(l => l.Split(',').Select(i => double.Parse(i)).ToArray());
}

PS: не имея второго ToArray(), вы получите IEnumerable. Для большого файла вы можете просто использовать StreamReader и ReadLine в цикле и анализировать, что будет более эффективным с точки зрения производительности, я думаю.

Другие вопросы по тегам