Come posso analizzare questa matrice in Java?
Solo per divertimento, ho deciso di voler scrivere un programma Python che esegue operazioni matematiche su Matrici (raccolte rettangolari di dati numerici) senza utilizzare la libreria NumPy, che era stata creata appositamente per la matematica a matrice (Algebra lineare). Ho completato quel programma in Python, ma da allora ho deciso di provare a trasformarlo in codice Java. Poiché Python non è strettamente tipizzato come Java, il mio problema attualmente è analizzare l'input della matrice di stringhe dell'utente nel modulo x x x, x x x, x x x, ..., in cui ogni numero è separato da uno spazio e ogni riga è separata da una virgola e uno spazio. Devo analizzarlo[[x, x, x], [x, x, x], [x, x, x], [...]]
Ho creato una funzione separata che restituirà double[][] matrixe riceverà l'input dell'utente, ma per il test ho lasciato il suo tipo di ritorno vuoto e gli ho dato una matrice predefinita [[1, 2, 3], [4, 5, 6], [7, 8, 9]]nel modulo"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");
}
In questo codice di test, voglio che venga stampato [[1, 2, 3], [4, 5, 6], [7, 8, 9]]3 volte, ma viene stampato [1 2 3, 4 5 6, 7 8 9]3 volte. Cosa mi manca?
Risposte
L'output è un array 2D, quindi l'analisi dovrebbe essere eseguita come tale.
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(" ")chiamata restituisce un array di risultati, che stai ignorando, ma non modifica l'array originale . È necessario utilizzare il suo risultato per memorizzare la riga appena analizzata da qualche parte:
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;
}
Se ti accontenti di Double [] [] un one liner è possibile
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);
}
È fondamentalmente un formato csv, quindi commons-csv fa anche il lavoro di analisi, con alcune brutte modifiche:
List<CSVRecord> rows = CSVFormat.DEFAULT.withDelimiter(' ')
.parse(new StringReader(matrix.replace(", ", "\n")))
.getRecords();
Alcuni pensano che tutta questa roba di oggetti, suddivisione e streaming e libreria sia davvero scadente ed è molto più interessante creare questa funzionalità interamente in modalità in prima persona, vecchia scuola di basso livello, scanner, parser, cosa no, in la venerabile, secolare tradizione ascetica di usare char[]solo. È possibile , e in questo modo è anche possibile aumentare il LoC di un fattore 70 senza introdurre codice non necessario, beh ... non molto, unit test non contati.