Bu Matrisi Java'da nasıl ayrıştırırım?

Nov 10 2020

Sırf eğlenmek için, özellikle matris matematiği (Doğrusal Cebir) için tasarlanmış NumPy kütüphanesini kullanmadan Matrisler üzerinde matematiksel işlemler (sayı verilerinin dikdörtgen koleksiyonları) yapan bir Python programı yazmak istediğime karar verdim. Bu programı Python'da tamamladım, ancak o zamandan beri bunu Java koduna dönüştürmeye karar verdim. Python, Java gibi kesin bir şekilde yazılmadığından, şu anda benim sorunum kullanıcının dizeli matris girişini formda ayrıştırmak x x x, x x x, x x x, ..., burada her sayı bir boşlukla ayrılıyor ve her satır virgül ve boşlukla ayrılıyor. Onu ayrıştırmalıyım[[x, x, x], [x, x, x], [x, x, x], [...]]

double[][] matrixKullanıcı girdisini döndürecek ve alacak ayrı bir işlev oluşturdum , ancak test etmek için dönüş türünü geçersiz bıraktım [[1, 2, 3], [4, 5, 6], [7, 8, 9]]ve formda bir varsayılan matris verdim"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");
    }

Bu test kodunda [[1, 2, 3], [4, 5, 6], [7, 8, 9]]3 defa basılmasını istiyorum ama 3 defa basılmasını istiyorum [1 2 3, 4 5 6, 7 8 9]. Neyi kaçırıyorum?

Yanıtlar

1 Aman Nov 10 2020 at 18:08

Çıktınız 2D dizidir, bu nedenle ayrıştırma bu şekilde yapılmalıdır.

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

aString.split(" ")Çağrı sen görmezden geliyorsun sonuçların, bir dizi döndürür, ancak orijinal diziyi değiştirmez . Yeni ayrıştırılmış satırı bir yerde saklamak için sonucunu kullanmanız gerekir:

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

Double [] [] ile memnunsanız, tek satırlık bir çözüm olabilir

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

Temelde bir csv formatıdır, bu nedenle commons-csv birkaç çirkin ince ayar ile ayrıştırma işini de yapar:

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

Bazıları, tüm bu nesne, bölme ve akış ve kütüphane işlerinin gerçekten yetersiz olduğunu ve bu işlevi tamamen 1. kişi modunda, gerçekten düşük düzeyli eski okul, tarayıcı, ayrıştırıcı, ne olmasın içinde oluşturmak çok daha havalı olduğunu düşünüyor. asketik asketik char[]sadece kullanma geleneği . Onun Olası artırmak ve bu yolla onun da mümkündür LoC gereksiz kod tanıtan olmadan bir faktör 70 tarafından, pekala ... pek birim testleri sayılmaz.