2

I have the following array of regular expressions:

String[] array = new String[] { 
  "(car)|(truck)|(bus)|(van)", //4) transportation
  "(w)|(x)|(y)|(z)", //1) options
    "1|2|3|4", //2) numbers
    "(red)|(blue)|(green)|(pink)|(yellow)" //3) color
};

and I have the following string:

String s= "1 blue w truck";

I am trying to iterate over this string to see if any of the words in the string match any of the regular expressions in the array. This is what I am doing:

for(int i=0; i<array.length;i++){
      Pattern word = Pattern.compile(array[i]);
      Matcher match = word.matcher(s);
      while(match.find() ){
        System.out.println(String.format(" Using regex %d:  %s",i,match.group()));
      }
    }

This gives the following output:

Using regex 0:  truck
Using regex 1:  w
Using regex 2:  1
Using regex 3:  blue

But I want the following to be the output:

Using regex 2:  1
Using regex 3:  blue
Using regex 1:  w
Using regex 0:  truck

I want the words in the strings to stay in the same order without changing the order of the regular expressions in the array.

3
  • 2
    You will need to loop on parts of the string instead then. This might be a bit less efficient, as you will then also need to loop through each of the regexes until you hit a match also. Commented May 4, 2016 at 13:22
  • Would it be a valid solution for you to combine the pattern array to one regular expression? Or is the pattern array a must have? Commented May 4, 2016 at 13:44
  • @Alexander I can't do that. I have to distinguish which thing I found in the string Commented May 4, 2016 at 13:53

4 Answers 4

3

Here's a solution using a pojo that will contain the relevant information of your matches (arbitrarily called MatchInfo here), and a TreeSet ordering your matches by the required criterion (the index of the match within the given String).

// your patterns
String[] array = new String[] { 
    "(car)|(truck)|(bus)|(van)", // 4) // transportation
    "(w)|(x)|(y)|(z)", // 1) options
    "1|2|3|4", // 2) numbers
    "(red)|(blue)|(green)|(pink)|(yellow)" // 3) color
};
// your input
String s = "1 blue w truck";

// the definition of the relevant information you want to keep on matches
class MatchInfo implements Comparable<MatchInfo>{
    int index;
    Integer start;
    String match;
    MatchInfo(int index, int start, String match) {
        this.index = index;
        this.start = start;
        this.match = match;
    }
    @Override
    // comparing start index of the match within original string
    public int compareTo(MatchInfo o) {
        return start.compareTo(o.start);
    };
}
// orders unique elements by natural ordering, as defined by Comparable 
// implementation
Set<MatchInfo> groups = new TreeSet<>();

// your original iteration
for (int i = 0; i < array.length; i++) {
    Pattern word = Pattern.compile(array[i]);
    Matcher match = word.matcher(s);
    while (match.find()) {
        // adding new "MatchInfo" to the set
        groups.add(new MatchInfo(i, match.start(), match.group()));
    }
}

// iterating and printing the info
for (MatchInfo m: groups) {
    System.out.printf("Using regex %d: %s%n", m.index, m.match);
}

Output

Using regex 2: 1
Using regex 3: blue
Using regex 1: w
Using regex 0: truck
Sign up to request clarification or add additional context in comments.

Comments

2

You will need to loop on parts of the string instead. This might be a bit less efficient, as you will then also need to loop through each of the regexes until you hit a match also.

Something like the following should help:

String[] parts = s.split(" ");
for (int i = 0; i < parts.length; i++) {
    for (int r; r < array.length; r++) {
        Pattern word = Pattern.compile(array[i]);
        Matcher match = word.matcher(s);
        if (match.find()) {
            // print out stuff
            break;
        }
    }
}

1 Comment

As @dimplex pointed out in their answer, I am unnecessarily recompiling the patterns in the array on each iteration. An optimization would involve precompiling all of the patterns, as their answer demonstrates.
0

Compiling the pattern on each iteration is not necessary.

        Pattern[] array = new Pattern[] { 
              Pattern.compile("^((car)|(truck)|(bus)|(van))"), //4) transportation
              Pattern.compile("^((w)|(x)|(y)|(z))"), //1) options
              Pattern.compile("^(1|2|3|4)"), //2) numbers
              Pattern.compile("^((red)|(blue)|(green)|(pink)|(yellow))") //3) color
            };
    String s= "1 blue w truck";

    while(s.length() > 0) {
        for(int i=0; i<array.length;i++){
          Matcher match = array[i].matcher(s);
          if(match.find()) {
              String substr = match.group();
              System.out.println(String.format(" Using regex %d:  %s",i, substr));
              s = s.substring(substr.length()).trim();
          }
        }
    }

Comments

0

Another possibility would be using a more complex regular expression and use capturing groups. I added a little extra to provide you a type string by using named capturing groups in the regular expression. If you don't like it you may use groupCount() and group(i) iteration to return the matched group index.

    public static void main() {
      Pattern pattern = Pattern.compile("(?<transportation>(?:car)|(?:truck)|(?:bus)|(?:van))|(?<options>[wxyz])|(?<numbers>[1-4])|(?<color>(?:red)|(?:blue)|(?:green)|(?:pink)|(?:yellow))");

      String s = "1 blue w truck";

      Matcher match = pattern.matcher(s);
      while(match.find()) {
        printGroupMatch(match, "transportation");
        printGroupMatch(match, "options");
        printGroupMatch(match, "numbers");
        printGroupMatch(match, "color");
      }
    }

    private static void printGroupMatch(Matcher match, String gName) {
      String groupValue = match.group(gName);
      if(groupValue != null){
        System.out.println(String.format(" Using regex %s:  %s", gName, groupValue));
    }
  }

This will return you something like this:

 Using regex numbers:  1
 Using regex color:  blue
 Using regex options:  w
 Using regex transportation:  truck

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.