Как мне разобрать эту матрицу на Java?
Ради интереса я решил, что хочу написать программу на Python, которая выполняет математические операции с матрицами (прямоугольные коллекции числовых данных) без использования библиотеки NumPy, которая была создана специально для матричной математики (линейная алгебра). Я завершил эту программу на Python, но с тех пор решил, что хочу попытаться превратить это в код Java. Поскольку Python не является строго типизированным, как Java, моя проблема в настоящее время заключается в анализе ввода строковой матрицы пользователя в форме x x x, x x x, x x x, ..., где каждое число разделяется пробелом, а каждая строка разделяется запятой и пробелом. Я должен разобрать это на[[x, x, x], [x, x, x], [x, x, x], [...]]
Я создал отдельную функцию, которая будет возвращать double[][] matrixи получать вводимые пользователем данные, но для тестирования я оставил ее тип возвращаемого значения void и присвоил ей матрицу по умолчанию [[1, 2, 3], [4, 5, 6], [7, 8, 9]]в форме"1 2 3, 4 5 6, 7 8 9"
// Takes text input; transforms it into array of arrays (matrix)
// parse 'x x x, x x x, ...' into [[x, x, x], [x, x, x], [...]]
private static void parseMatrix(String matrix) {
String[] partMat = matrix.strip().split(", "); // Separates each row (one array results)
for(int i = 0; i < partMat.length; i++) { // Supposed to create arrays out of rows (multiple arrays result)
partMat[i].split(" ");
System.out.println(Arrays.toString(partMat));
}
}
public static void main(String[] args) {
parseMatrix("1 2 3, 4 5 6, 7 8 9");
}
В этом тестовом коде я хочу, чтобы он печатался [[1, 2, 3], [4, 5, 6], [7, 8, 9]]3 раза, но он печатается [1 2 3, 4 5 6, 7 8 9]3 раза. Что мне не хватает?
Ответы
Ваш вывод - это 2D-массив, поэтому синтаксический анализ должен выполняться как таковой.
private static double[][] parseMatrix(String matrix) {
String[] parentMat = matrix.split(", ");
double[][] childMat = new double[parentMat.length][];
for (int i = 0; i < parentMat.length; i++) {
String[] child = parentMat[i].split(" ");
childMat[i] = new double[child.length];
for (int j = 0; j < child.length; j++) {
childMat[i][j] = Double.parseDouble(child[j]);
}
}
System.out.print(Arrays.deepToString(childMat)); //[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]
return childMat;
}
aString.split(" ")Вызов возвращает массив результатов, которые вы игнорируете, но не изменяет исходный массив . Вам нужно использовать его результат для хранения где-нибудь вновь проанализированной строки:
private static double[][] parseMatrix(String matrix) {
String[] partMat = matrix.strip().split(", ");
double[][] rows = new double[partMat.length][];
for(int i = 0; i < partMat.length; i++) {
String[] row = partMat[i].split(" "); // <-- store result
System.out.println(Arrays.toString(row));
// will fail unless you use Double.valueOf to parse each element
// rows[i] = row;
}
return rows;
}
Если вас устраивает Double [] [], можно использовать однострочник
private static Double[][] parseMatrix(String matrix) {
return Stream.of(matrix.split(", "))
.map(row -> Stream.of(row.split(" ")).map(Double::valueOf).toArray(Double[]::new))
.toArray(Double[][]::new);
}
По сути, это формат csv, поэтому commons-csv также выполняет работу по синтаксическому анализу с некоторыми уродливыми настройками:
List<CSVRecord> rows = CSVFormat.DEFAULT.withDelimiter(' ')
.parse(new StringReader(matrix.replace(", ", "\n")))
.getRecords();
Некоторые думают, что весь этот объектный, сплит-, потоковый и библиотечный материал на самом деле отстой, и гораздо круче создать эту функциональность полностью в режиме от первого лица, действительно низкоуровневой старой школы, сканера, парсера, чего нет, в почтенная, многовековая аскетическая традиция употребления char[]только. Это возможно , и таким образом также возможно увеличить LoC в 70 раз без добавления ненужного кода, ну ... не намного, модульные тесты не учитываются.