alvas alvas - 4 months ago 10
Java Question

Converting a string into a double[][] - Java

Since Java doesn't have an

module, and I want to write my own regex to parse strings into a
double[][]
, e.g.

[in]:

`{{1.23,8.4},{92.12,-0.57212}}`
`{{1.23,-8.4}, {-92.12,-0.57212}}`


[code]:

double[][] xArr;
// Somehow read the string into something like this:
xArr = new double[][] {{1.23,8.4},{92.12,-0.57212}};
System.out.println(xArr[0][0] + " " + xArr[0][1]);


[out]:

1.23 -8.4


Currently, I'm doing it as such:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import java.util.ArrayList;
import java.util.List;

public class HelloWorld {

public static void main(String[] args) {
String s = "{{1.23,8.4}, {92.12,-0.57212}}";

Pattern regex = Pattern.compile("((-)?\\d+(?:\\.\\d+)?)");
Matcher matcher = regex.matcher(s);
List<double[]> locations = new ArrayList<double[]>();
int i = 0;
while(matcher.find()){
double d1 = Double.parseDouble(matcher.group(1));
matcher.find();
double d2 = Double.parseDouble(matcher.group(1));
locations.add(new double[] {d1, d2});
i++;
};


}

}


Is there a better way to do this? I.e.:


  • Now, the code is sort of cheating by know that my inner size of the double[][] is 2 and during iteration through
    match.find()
    . It does 2 passes to skip to the next pair, is there a way to change the regex such that it extracts 2 groups at a time?

  • Currently it's reading into the
    d1
    and
    d2
    variable before create a new
    double[]
    to add to the
    List
    , is there a way to do it directly without creating
    d1
    and
    d2
    ?


Answer

Here is a Java 8 solution I came up with:

String test = "{{1.23,8.4},{92.12,-0.57212}}";

double[][] vals = Arrays.stream(test.replaceAll(" ", "").split("},\\{"))
                        .map(str -> str.replaceAll("[{}]", "").split(","))
                        .map(Arrays::stream)
                        .map(stream -> stream.mapToDouble(Double::parseDouble)
                                             .toArray())
                        .toArray(double[][]::new);

System.out.println(Arrays.deepToString(vals));

Output:

[[1.23, 8.4], [92.12, -0.57212]]

Or if you want a Double[][]:

Double[][] vals = Arrays.stream(test.replaceAll(" ", "").split("},\\{"))
                        .map(str -> str.replaceAll("[{}]", "").split(","))
                        .map(Arrays::stream)
                        .map(stream -> stream.map(Double::parseDouble)
                                             .toArray(Double[]::new))
                        .toArray(Double[][]::new);

Explanation:

First any whitespace is removed and the string is split on the pattern },\\{ which will result in a String[] where each String is one of the double[]s with some excess curly braces:

["{{1.23,8.4", "92.12,-0.57212}}"]

Then, for each String the curly braces are removed, and the String is split again. So each String becomes a String[] where each value is the String representation of a "double":

[["1.23", "8.4"],["92.12", "-0.57212"]]

These strings are then parsed into doubles, and everything is collected into a double[] and then a double[][]:

[[1.23, 8.4], [92.12, -0.57212]]
Comments