0

I want to split data from file which have the following format: {[(1;1;2),(5;1;2),(5;1;1)],[(1;3;2),(5;3;2),(5;1;2)]}

And here is my Java method for that:

public void createFromFile(String filename) throws IOException{
    BufferedReader br = new BufferedReader(new FileReader(filename));
    String s;
    while ((s = br.readLine()) != null) 
    {
        s = s.replace("{", "").replace("}", "").replace("]", "").replace(",", "");
        ArrayList<Surface> sf = new ArrayList<Surface>();
        for(String s1: s.split("\\["))
        { // <== not splitting here
            ArrayList<Point> tp = new ArrayList<Point>();
            for(String s2: s1.split("\\("))
            { // <== here neither
                String[] s3 = s2.split(";");
                tp.add(new Point(Double.valueOf(s3[0]),Double.valueOf(s3[1]),Double.valueOf(s3[2])));
            }
            sf.add(new Surface((Point[]) tp.toArray()));
        }
        convShape.add(new Body((Surface[])sf.toArray()));   
    }
}

why does s.split("\\[") and s.split("\\(") do not split s?

4
  • sorry, I'll edit it right now. Commented Oct 29, 2012 at 12:46
  • So you want all the numbers between brackets Commented Oct 29, 2012 at 12:46
  • Yes, but want them grouped by "("")" too, and then by "[""]", and finally by "{""}" Commented Oct 29, 2012 at 12:48
  • 4
    Ughh - what a horrible way to implement a parser ... Commented Oct 29, 2012 at 12:48

3 Answers 3

1

Well, I think that should work. As far as your current code is concerned, it should correctly split it.

But, given that you just want the numbers inside the brackets. You don't need a split here. You are making your job tough. You should better use Pattern and Matcher class, to find everything in between ( and ). You can use the below code for your help: -

    String str = "{[(1;1;2),(5;1;2),(5;1;1)],[(1;3;2),(5;3;2),(5;1;2)]}";

    Pattern pattern = Pattern.compile("(\\(\\d;\\d;\\d\\),?){3}");
    Matcher matcher = pattern.matcher(str);

    while (matcher.find()) {
        int i = 1;
        System.out.println("Polygon Coordinates: ");
        String[] coordinates = matcher.group(0).split(",");

        for (String point: coordinates) {
            System.out.println("Coordinate " + (i++) + ": " + point);

            point = point.replace("\\(", "").replace("\\)", "");
            String[] s3 = point.split(";");
            tp.add(new Point(Double.valueOf(s3[0]), Double.valueOf(s3[1]),
                             Double.valueOf(s3[2])));

        }

        sf.add(new Surface((Point[]) tp.toArray()));
        System.out.println();
    }

OUTPUT: -

Polygon Coordinates: 
Coordinate 1: (1;1;2)
Coordinate 2: (5;1;2)
Coordinate 3: (5;1;1)

Polygon Coordinates: 
Coordinate 1: (1;3;2)
Coordinate 2: (5;3;2)
Coordinate 3: (5;1;2)

Explanation: -

  • (\\(\\d;\\d;\\d\\),?){3} - This matches 3 groups of 3 integers separated by a ; inside brackets, with groups separated by comma(,). Then it captures the complete match.

  • matcher.find() - Finds everything from the string, that matches the above pattern.

  • matcher.group(0) - Gets the complete match.

  • Split the complete match on comma(,) to get individual coordinates

  • If you want to match double or integer values separated by ;, you would need to change the Regex a little bit. That I leave to you.

  • See Pattern class docs for more details on various quantifiers. {3} in the above regex is one of the quantifiers.

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

5 Comments

Close enough! but it doesn't group (1;1;2) (5;1;2) (5;1;1). (x;y;z) are the coordinate of some top of a polygon, so I really need them grouped :)
@mhfff32. Ok. I'll change the regex.
@mhfff32. Changed Regexp. You can try that.
+1, very clean attempt (especially compared to the code in the answer)
@Downvoter can you please comment to make your downvote more meaningful?
0

A better way would be to match the required data in groups

Matcher matcher1 = Pattern.compile("(?<=\\{).*?(?<=\\})").matcher(yourInput);
while(mather1.find())
{
    Matcher matcher2 = Pattern.compile("(?<=\\[).*?(?=\\])").matcher(matcher1.Group());
    while (matcher2.find()) 
    {
        Matcher matcher3 = Pattern.compile("(\\d+);(\\d+);(\\d+)").matcher(matcher2.Group());
    while (matcher3.find()) 
    {

        tp.add(new Point(Double.valueOf(matcher3.Group(1),Double.valueOf(matcher3.Group(2)),Double.valueOf(matcher3.Group(3))));
    }
       sf.add(new Surface((Point[]) tp.toArray()));  
    }
convShape.add(new Body((Surface[])sf.toArray()));   
}

Comments

0

Well, it smells like JSON, but if you want to use split, then

  • to get groups find all matches of /[\\d;]+/
  • to get numbers from the groups, use split using ";"

Demo:

import java.util.*;
import java.lang.*;
import java.util.regex.*;

class Main
{
  public static void main (String[] args) throws java.lang.Exception
  {
    String str = "{[(1;1;2),(5;1;2),(5;1;1)],[(1;3;2),(5;3;2),(5;1;2)]}";
    Pattern pattern = Pattern.compile("[\\d;]+");
    Matcher matcher = pattern.matcher(str);
    while (matcher.find()) {
        System.out.println(matcher.group(0));
        String[] numbers = matcher.group(0).split(";");
        int i = 1;
        for (String number: numbers) {
            System.out.println("Parameter #" + i + ": " + number);
            i++;
        }
        System.out.println();
    }   
  }
}

Output:

1;1;2
Parameter #1: 1
Parameter #2: 1
Parameter #3: 2

5;1;2
Parameter #1: 5
Parameter #2: 1
Parameter #3: 2

5;1;1
Parameter #1: 5
Parameter #2: 1
Parameter #3: 1

1;3;2
Parameter #1: 1
Parameter #2: 3
Parameter #3: 2

5;3;2
Parameter #1: 5
Parameter #2: 3
Parameter #3: 2

5;1;2
Parameter #1: 5
Parameter #2: 1
Parameter #3: 2

Test this demo here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.