How to convert a string that contains doubles into a matrix in java

Viewed 152
String a = "0 2 4 1 4.5 2.2 1.1 4.3 5.2";

Here we have a String of 9 numbers, some of which are double, and some of which are int. I need to convert this into a matrix and when I am given only integer values in the String, it is fairly easy because all I do cast double on a whole integer after I parseInt for each String value that is a digit.

For instance,

String a = "1 2 3 4 5 6 7 8 9";
double[][] matrixA = new double[3][3];
int counter = 0;
for (int i = 0; i <= a.length(); i++) {
    char c = a.charAt(i);
    if (c == ' ') {
        counter = counter;
    } else {
        counter++;
        double k = Double.parseDouble(String.valueOf(c));
        if (counter <= 3) {
            matrixA[0][counter - 1] = k;
        } else if (counter > 3 && counter <= 6) {
            matrixA[1][counter - 4] = k;
        } else {
            matrixA[2][counter - 7] = k;
        }
    }
}

This gives me a 3-by-3 matrix that goes from 1-9. However, when I am given a string that contains real numbers or 'doubles' my method fails to create a matrix because it counts each element of the string, one of which is a period. So how can I create a 3-by-3 matrix when the String that is given to me contains a double?

3 Answers

Answer by @rempas is good, though I would replace the calculation of the input index with a simple "next value" index.

String a = "1 2 -3 4.5 5 6.5 7.5 8 9";
double[][] matrix = new double[3][3];
String[] nums = a.split(" ");
for (int i = 0, k = 0; i < matrix.length; i++) { // <== Initialize k here
    for (int j = 0; j < matrix[i].length; j++) {
        matrix[i][j] = Double.parseDouble(nums[k++]); // <== Simpler code
    }
}
System.out.println(Arrays.deepToString(matrix));

Output

[[1.0, 2.0, -3.0], [4.5, 5.0, 6.5], [7.5, 8.0, 9.0]]

Jagged Array

That will make it work even if the 2D array is jagged.

String a = "1 2 -3 4.5 5 6.5 7.5 8 9";
double[][] matrix = new double[][] { new double[2], new double[3], new double[4] }; // <== Jagged array
String[] nums = a.split(" ");
for (int i = 0, k = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        matrix[i][j] = Double.parseDouble(nums[k++]);
    }
}
System.out.println(Arrays.deepToString(matrix));

Output

[[1.0, 2.0], [-3.0, 4.5, 5.0], [6.5, 7.5, 8.0, 9.0]]

Scanner

Alternatively, instead of split() and k++ logic, use a Scanner.

String a = "1 2 -3 4.5 5 6.5 7.5 8 9";
double[][] matrix = new double[3][3];
try (Scanner sc = new Scanner(a)) { // <== Use Scanner
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            matrix[i][j] = sc.nextDouble(); // <== Use Scanner
        }
    }
}
System.out.println(Arrays.deepToString(matrix));

Output

[[1.0, 2.0, -3.0], [4.5, 5.0, 6.5], [7.5, 8.0, 9.0]]

This should do the trick for doubles as well as negative numbers. Notice the conversion from matrix coordinates to index index = x + y * width

String a = "1 2 -3 4.5 5 6.5 7.5 8 9";
double[][] matrix = new double[3][3];
String[] nums = a.split(" ");

for(int i = 0; i < matrix.length; i++){
    for(int j = 0; j < matrix[0].length; j++){
        matrix[i][j] = Double.parseDouble(nums[matrix[j].length * i + j]);
    }
}

You can split this string into an array, then parseDouble values from the substrings, and then collect a new 2d array with rows of a specified length as follows:

String a = "0 2 4 1 4.5 -2.2 1.1 4.3 5.2";
// array of numbers as strings
String[] b = a.split(" ");
// length of the row
int m = 3;
// 2d array with rows of a specified
// length, or less if not possible
double[][] dd = IntStream
        // iterate over the indices of
        // the string array with step 'm'
        .iterate(0, i -> i < b.length, i -> i + m)
        // subarray of a specified length at each step
        .mapToObj(i -> Arrays
                // substream with a specified
                // range, or less if not possible
                .stream(b, i, Math.min(i + m, b.length))
                // string to double
                .mapToDouble(Double::parseDouble)
                .toArray())
        .toArray(double[][]::new);

// output
Arrays.stream(dd).map(Arrays::toString).forEach(System.out::println);
//[0.0, 2.0, 4.0]
//[1.0, 4.5, -2.2]
//[1.1, 4.3, 5.2]

See also: Copying a 1d array to a 2d array

Related