0

I have a string:

String stringProfile = "0, 4.28 10, 4.93 20, 3.75";

I am trying to turn it into an array like as follows:

double [][] values = {{FastMath.toRadians(0), FastMath.toRadians(4.28)},
                      {FastMath.toRadians(10), FastMath.toRadians(4.93)},
                      {FastMath.toRadians(20), FastMath.toRadians(3.75)}}; 

Where FastMath.toRadians is a method on each element.

Number of issues:

First logical thing to do is to split the string:

List<String> stringProfileList= Arrays.asList(stringProfile.split(" "));

The output would be "0, 4.28, 10, 4.93, 20, 3.75", so now every element is split by a "," rather than every other.

Then for every 2 elements in the list, I need to assign to an array. Within each Array I apply the FastMath.toRadians() on each element and then I append each array to a larger multidimensional array.

Is this the right way to go about this? I'm getting stuck at implementing for every 2 elements.

I also need to convert these string elements into a double, which doesn't seem to trivial.

0

3 Answers 3

1

If you want to use Stream try this:

    Pattern PAIR = Pattern.compile("(?<=\\d)\\s(?=\\d)");

    double[][] result = PAIR.splitAsStream(stringProfile)
            .map(pair -> pair.split(","))
            .map(pair -> new double[] { FastMath.toRadians(Double.valueOf(pair[0])), FastMath.toRadians(Double.valueOf(pair[1])) })
            .toArray(i -> new double[i][]);

A Pattern is used to split stringProfile on whitespace characters which have a digit behind and ahead them. This results in a Stream of strings which contains a pair of numbers divided by ', '. We split this string on ',' in a first map to get an array of strings representing the numbers. In the next map the numbers a parsed and their radians is computed.

We could devide the parsing of the numbers and the comuputation of the radians to single map steps. The following code is more verbose but creates an additional double array:

double[][] result = PAIR.splitAsStream(stringProfile)
        .map(pair -> pair.split(","))
        .map(pair -> new double[] { Double.valueOf(pair[0]), Double.valueOf(pair[1]) })
        .map(pair -> new double[] { FastMath.toRadians(pair[0]), FastMath.toRadians(pair[1]) })
        .toArray(i -> new double[i][]);

If we want to reuse the double array, we can do this like this:

        .map(pair -> {
            pair[0] = FastMath.toRadians(pair[0]);
            pair[1] = FastMath.toRadians(pair[1]);
            return pair;
        })

The last step collects the double arrays into a two dimensional array.


EDIT:

Have a look on this demo.

Using the wording of the documentation of the Pattern class the used pattern looks for a whitespace character (\\s) which is preceded ((?<=\\d) = look behind) and succeeded ((?=\\d) = look ahead) by one digit (\\d). These looks have zero-width, thus they are evaluated for capturing (matching) but are not part of the matched sequence (Matcher.group()). The matching sequence contains only a whitespace character (\\s).

For stringProfile this pattern will match in two cases: "8 1" and "3 2". In these cases two digits are surrounding a " ". On the other hand e.g. "0, 4" doesn't match. The occurrence of "," prevents a match.

Sign up to request clarification or add additional context in comments.

6 Comments

pity u deleted that answer though, was working on some suggestions... since you deleted it, I added it don't rush next time
@Eugene Don't worry. I wasn't convinced myself after reading the specification. Maybe I'll come up with a better solution.
I really like this solution. I'd confused by the syntax of the regex. Could you break that down how it works? Cheers
@arsenal88 I've updated my answer.
Thanks, appreciated. I'm confused by the \\d notation. As this should take any digit, but it doesnt recognise negatives. I cant find notation for optional negatives on digits.
|
1

You are correct, first split the string to a list of substrings, then do a foreach over the list and add your FastMath torad result to a new resultlist:

List<String> list = new ArrayList<String>();
List<Double> results = new ArrayList<Double>();
for (String string : list) {
   results.add(FastMath.toRadians(Double.valueOf(string)));
}
results.toArray();

the next thing you do is split the array to a new multi dimensional array of your choice, by iterating over it and sorting it into your multidimensional array.

However If you're not forced to use arrays I'd use a higher datataype like maps or lists, or a tuple or something better suiting your needs. Just check out what java collections offers you.

Comments

0

If you split on a space not preceded by a comma you get comma-separated pairs. These can then be split again and mapped into Double[].

You can add any further processing afterwards.

private void test() {
    String s = "0, 4.28 10, 4.93 20, 3.75";
    // Split on space without comma beforehand.
    Double[][] doubles = Arrays.stream(s.split("(?<!,) "))
            // Then split each pair.
            .map(pairString -> pairString.split(", "))
            // Make each pair into a Double[]
            .map(pair -> new Double[]{Double.valueOf(pair[0]), Double.valueOf(pair[1])})
            // to array of Double[][]
            .toArray(Double[][]::new);
    System.out.println(Arrays.deepToString(doubles));
}

[[0.0, 4.28], [10.0, 4.93], [20.0, 3.75]]

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.