mhfff32
mhfff32

Reputation: 293

regex for java split

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?

Upvotes: 0

Views: 260

Answers (3)

Rohit Jain
Rohit Jain

Reputation: 213223

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.

Upvotes: 1

Ωmega
Ωmega

Reputation: 43673

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.

Upvotes: 0

Anirudha
Anirudha

Reputation: 32797

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

Upvotes: 0

Related Questions