¿Cómo analizo esta matriz en Java?
Solo por diversión, decidí que quería escribir un programa de Python que realiza operaciones matemáticas en Matrices (colecciones rectangulares de datos numéricos) sin usar la biblioteca NumPy, que fue construida específicamente para matemáticas matriciales (Álgebra lineal). Completé ese programa en Python, pero desde entonces decidí que quería intentar convertirlo en código Java. Dado que Python no está escrito estrictamente como Java, mi problema actualmente es analizar la entrada de matriz de cadenas del usuario en el formulario x x x, x x x, x x x, ..., donde cada número está separado por un espacio y cada fila está separada por una coma y un espacio. Tengo que analizar eso en[[x, x, x], [x, x, x], [x, x, x], [...]]
He creado una función separada que devolverá double[][] matrixy recibirá la entrada del usuario, pero para las pruebas dejé su tipo de retorno vacío y le di una matriz predeterminada de [[1, 2, 3], [4, 5, 6], [7, 8, 9]]en el formulario"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");
}
En este código de prueba, quiero que se imprima [[1, 2, 3], [4, 5, 6], [7, 8, 9]]3 veces, pero se imprime [1 2 3, 4 5 6, 7 8 9]3 veces. ¿Qué me estoy perdiendo?
Respuestas
Su salida es una matriz 2D, por lo que el análisis debe realizarse como tal.
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;
}
La aString.split(" ")llamada devuelve una matriz de resultados, que está ignorando, pero no modifica la matriz original . Debe usar su resultado para almacenar la fila recién analizada en algún lugar:
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;
}
Si está satisfecho con Double [] [], es posible usar una sola línea
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);
}
Es básicamente un formato csv, por lo que commons-csv también hace el trabajo de análisis, con algunos ajustes feos:
List<CSVRecord> rows = CSVFormat.DEFAULT.withDelimiter(' ')
.parse(new StringReader(matrix.replace(", ", "\n")))
.getRecords();
Algunos piensan que todo este objeto, división, flujo y biblioteca es realmente aburrido y es mucho más genial crear esta funcionalidad completamente en el modo de primera persona, la vieja escuela de muy bajo nivel, escáner, analizador, lo que no, en la venerable y centenaria tradición ascética de consumir char[]solamente. Es posible , y de esta manera también es posible aumentar el LoC en un factor 70 sin introducir código innecesario, bueno ... no mucho, las pruebas unitarias no cuentan.