Comment analyser cette matrice en Java?

Nov 10 2020

Juste pour le plaisir, j'ai décidé que je voulais écrire un programme Python qui effectue des opérations mathématiques sur des matrices (collections rectangulaires de données numériques) sans utiliser la bibliothèque NumPy, qui était spécialement conçue pour les mathématiques matricielles (algèbre linéaire). J'ai terminé ce programme en Python, mais depuis, j'ai décidé d'essayer de le transformer en code Java. Étant donné que Python n'est pas strictement typé comme Java, mon problème consiste actuellement à analyser l'entrée de la matrice à chaînes de l'utilisateur dans le formulaire x x x, x x x, x x x, ..., où chaque nombre est séparé par un espace et chaque ligne est séparée par une virgule et un espace. Je dois analyser cela en[[x, x, x], [x, x, x], [x, x, x], [...]]

J'ai créé une fonction distincte qui renverra le double[][] matrixet recevra une entrée de l'utilisateur, mais pour le test, j'ai laissé son type de retour vide et lui ai donné une matrice par défaut de [[1, 2, 3], [4, 5, 6], [7, 8, 9]]sous la forme"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");
    }

Dans ce code de test, je veux qu'il s'imprime [[1, 2, 3], [4, 5, 6], [7, 8, 9]]3 fois, mais il imprime [1 2 3, 4 5 6, 7 8 9]3 fois. Qu'est-ce que je rate?

Réponses

1 Aman Nov 10 2020 at 18:08

Votre sortie est un tableau 2D, donc l'analyse doit être effectuée en tant que telle.

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;
}
2 tucuxi Nov 10 2020 at 18:03

L' aString.split(" ")appel renvoie un tableau de résultats, que vous ignorez, mais ne modifie pas le tableau d'origine . Vous devez utiliser son résultat pour stocker la ligne nouvellement analysée quelque part:

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;
}
NikolaiDmitriev Nov 10 2020 at 23:16

Si vous êtes satisfait de Double [] [], une seule ligne est possible

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);
}

Il s'agit essentiellement d'un format csv, donc commons-csv effectue également le travail d'analyse, avec quelques modifications laides:

List<CSVRecord> rows = CSVFormat.DEFAULT.withDelimiter(' ')
            .parse(new StringReader(matrix.replace(", ", "\n")))
            .getRecords();

Certains pensent que tout ce truc d'objet, de fractionnement et de flux et de bibliothèque est vraiment nul et il est beaucoup plus cool de créer cette fonctionnalité entièrement en mode 1ère personne, de la vieille école vraiment de bas niveau, du scanner, de l'analyseur, etc. la vénérable tradition ascétique vieille de plusieurs siècles de n'utiliser char[]que. C'est possible , et de cette façon, il est également possible d'augmenter la LoC d'un facteur 70 sans introduire de code inutile, enfin ... pas grand chose, les tests unitaires ne comptent pas.