Как прочитать 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 в цикле и анализировать, что будет более эффективным с точки зрения производительности, я думаю.