arjacsoh
arjacsoh

Reputation: 9232

Regex to find if a specific character exists odd times in String

Is there any way to write a regular expression in Java which finds if a String contains an odd number of a specific character i.e. "a"? I have done it writing more verbose code, using namely the following method:

public static boolean hasEvenNumber(String s) {
        int count = 0;

        Pattern p = Pattern.compile("(^a)*(a)");
        Matcher m = p.matcher(s);
        while (m.find())
            count++;

        if (count % 2 != 0)
            return true;
        return false;
    }

If for example one passes the String "jsadaajaaikadjasl" as parameter, then it retuns true, since it contains 7 "a". Is there a more elegant way to achieve it using only a regex and checking it like:

Pattern p = Pattern.compile(...);
Matcher m = p.matcher(s);
if(m.matches())
   return true;  

?

Upvotes: 6

Views: 4501

Answers (8)

Melih Altıntaş
Melih Altıntaş

Reputation: 2535

public static void main(String[] args) {

    String s = "jsadaajaaikadjasl";
    System.out.println(hasEvenNumber(s,"a"));
}

public static boolean hasEvenNumber(String s, String letter) {

    int count = s.length() - s.replaceAll(letter, "").length();
    return count % 2 == 0 ? false : true ;
}

Upvotes: 0

AppX
AppX

Reputation: 528

Here should be a working example of what you are trying to achive.

public static boolean hasEvenNumber(String s) {
    int counter = 0;
    Pattern p = Pattern.compile("([aA])?{1,}");
    Matcher m = p.matcher(s);
    while (m.find()) {
        if (m.group().equalsIgnoreCase("a"))
            counter++;
    }
    return (counter != 0 && counter%2==0);
}

Upvotes: 0

Pshemo
Pshemo

Reputation: 124225

I don't know why you want to use regex here (and I am not sure if I wan't to know) but you can try with [^a]*a([^a]*a[^a]*a)*[^a]*.

It means

[^a]*            # zero or more non-a characters 
                 # (in case string starts with non-a character)
a                # one "a" character 
([^a]*a[^a]*a)*  # two "a" characters preceded by zero or more non-a characters
                 # (this will match any numbers of "..a..a" "pairs")
[^a]*            # zero or more non-a characters 
                 # (in case string ends with non-a character)

In case you would like to match even numbers of a just remove [^a]*a from start or regex.

System.out.println("jsadaajaaikadjasl".matches("[^a]*a([^a]*a[^a]*a)*+[^a]*"));
System.out.println("jasadaajaaikadjasl".matches("[^a]*a([^a]*a[^a]*a)*+[^a]*"));

output:

true
false

Instead of regex you could use this simple method which will iterate over all string characters, compare them with searched one and each time when it find match flip boolean flag from odd to even or vice versa.

public static boolean hasOdd(String s, char character) {
    boolean response = false;
    for (char c : s.toCharArray())
        if (c == character)
            response = !response;
    return response;
}

//...

System.out.println(hasOdd("jsadaajaaikadjasl", 'a'));//true
System.out.println(hasOdd("jasadaajaaikadjasl", 'a'));//false

Upvotes: 4

Sazzadur Rahaman
Sazzadur Rahaman

Reputation: 7116

(?:([^a]*a[^a]*a[^a]*)*)

matches even numbers of a and

[^a]*a(?:([^a]*a[^a]*a[^a]*)*)

matches odd numbers of a.

Upvotes: 0

Kai Sternad
Kai Sternad

Reputation: 22830

I'd just count the characters and check that the String doesn't start with the character in question. You could use Apache Commons CharsetUtils for this:

public static boolean hasOddNumber(String s, char c) {
  boolean hasOddNumber = false; 
  if (s.charAt(0) != c){
    hasOddNumber = CharSetUtils.count(s, c) % 2 != 0;
  }
  return hasOddNumber;      

Also, I'd change the method name to hasOddNumber since your question implies that you want to know if a String has an odd number of occurrences.

Upvotes: 1

aim
aim

Reputation: 11

Odd: "^[^a]*(a[^a]*a[^a]*)*a[^a]*$"

Even: "^([^a]*a[^a]*a[^a]*)+$"

Upvotes: 1

anubhava
anubhava

Reputation: 785108

If you really need a regex then this code should work:

String str = "abadaa";
boolean isAOdd = str.matches("^[^a]*a(?=(([^a]*a){2})*[^a]*$).*$"); // false

str = "abadaacad";
isAOdd = str.matches("^[^a]*a(?=(([^a]*a){2})*[^a]*$).*$"); // true

Upvotes: 0

Holger
Holger

Reputation: 298153

Just create a pattern that matches an even count like "(?:[^a]*a[^a]*a)*" the add another occurrence, (?:[^a]*a[^a]*a)*[^a]*a[^a]. Now if matcher.matches returns true you have an odd number of occurrences.

Upvotes: 6

Related Questions