1

I'm trying to return a string of regular expression matches. Specifically, trying to return all vowels (aeiou) found in a string. The following code returns the 2 oo's but not the e. Expecting: eoo Getting: oo

Why is it not finding and appending the e to the StringBuilder object? Thank you.

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

class Main {
  public static void main(String[] args) {

    String inp = "Hello World!";
    System.out.println(vowelOnly(inp));
  }

  public static String vowelOnly(String input) {
    Pattern vowelPattern = Pattern.compile("[aeiou]+");
    Matcher vowelMatcher = vowelPattern.matcher(input);

    StringBuilder sb = new StringBuilder();

    int i = 0;
    if (vowelMatcher.find()) {
      while (vowelMatcher.find( )) {
        sb.append(vowelMatcher.group());
        i++;
      } 
      return sb.toString();
    } else {
      return "No matches";
    }
  }
}
3
  • 2
    you are not considering the result of first find, the one in if (vowelMatcher.find()) - remove that if and, if you really need the "No matches" return, test sb after the loop (I would prefer returning just the empty string, since that is what the method found [message, if needed, created by caller]) Commented Aug 16, 2019 at 8:16
  • If this is for a university project, returning "No matches" is acceptable. For almost every other context, it is better to return either an empty String, an Optional<String>, or throw an exception, but in this case, using an Optional or throwing an exception is probably overkill. Commented Aug 16, 2019 at 8:21
  • you can also just add sb.append(...group()) just after that if, but code repetition isn't that good Commented Aug 16, 2019 at 8:21

4 Answers 4

4

When you call vowelMatcher.find() inside your if condition, you tell the matcher to find the first string matching the specified pattern. In this case, it is "e". When you call it again in your while condition, the matcher finds the next match, in this case it is "o".

From there, it loops through the rest of the String. If you gave it the input "Hello World eeee", it would return "ooeeee", since you always discard the first match by calling .find() without calling .group() immediately after.

Change your loop to be like this, and it should work:

int i = 0;
while (vowelMatcher.find()) {
    sb.append(vowelMatcher.group());
    i++;
}

return i == 0 ? "No matches" : sb.toString();  // return "no matches" if i is 0, otherwise, string
Sign up to request clarification or add additional context in comments.

Comments

1

Your first call to vowelMatcher.find() in the if statement finds the "e" and the subsequent calls to vowelMatcher.find() in the while loop find all subsequent vowels.

Comments

0

Thats what you need:

 public static void main(String[] args) {
    String inp = "Hello World!";
    System.out.println(vowelOnly(inp));
  }

  public static String vowelOnly(String input) {
    Pattern vowelPattern = Pattern.compile("[aeiou]+");
    Matcher vowelMatcher = vowelPattern.matcher(input);

    StringBuilder sb = new StringBuilder();

    int i = 0;

    while (vowelMatcher.find()) {
      sb.append(vowelMatcher.group());
      i++;
    }
    return i == 0 ? "No matches" : sb.toString();
 }

Comments

0

That would probably be the solution you're looking for:

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

public class Main {

  public static void main(String[] args) {

    String inp = "Hello World!";
    System.out.println(vowelOnly(inp));
  }

  public static String vowelOnly(String input) {
    Pattern vowelPattern = Pattern.compile("[aeiou]+");
    Matcher vowelMatcher = vowelPattern.matcher(input);

    StringBuilder sb = new StringBuilder();

    while (vowelMatcher.find()) {
      sb.append(vowelMatcher.group());
    }

    if (sb.length() == 0) {
      return "No matches";
    }
    return sb.toString();
  }
}

Couple of notes:

  • You don't need to import java.lang.* classes.
  • With the matcher, whatever you find, you should group it immediately to collect.
  • You don't need the iteration variable. StringBuilder.length() would simply reveal if it's empty.

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.