Подсчет гласных, включенных между двумя согласными

1

Я пытаюсь найти из предложения слова, которые содержат две гласные между двумя r используя java. Поэтому я прочитал в предложении, а затем мне нужно найти слова, соответствующие критериям, описанным выше. Например, если у меня есть строка, такая как: "roar soccer roster reader", метод matches должен возвращать true для слов "рев" и "список",

Это метод, который я придумал, который выполняет работу

public boolean matches(String singleWord)
{
    // set count to -1. it will increase to 2 if a 'r' is found, it decreases for each vowel    
    int count = -1;
    // loop through a single word
    for (int i=0; i<singleWord.length(); i++){
        // if a 'r' is found set the count to two
        if(singleWord.charAt(i) == 'r'){
            // when count it 0 exit loop
            if (count == 0)
                return true;
            count = 2;}
        // if I find a vowel count decreases
        else if(isVowel(singleWord.charAt(i))){
            count--;}
    }
    return false;
}

но кажется немного неуклюжим... любое предложение о том, как его улучшить или сделать проще? спасибо !!!

на всякий случай, это метод isVowel

  private boolean isVowel(char c)
{
    String s = c + "";
    return "aeiou".contains(s);
}
Теги:
string

3 ответа

3
Лучший ответ

Вы можете сделать это, используя простой алгоритм без циклов:

  • Найдите индекс первого 'r'
  • Найдите индекс последнего 'r'
  • Вырежьте подстроку между двумя
  • Возвращает true если удаление всех гласных из подстроки сокращает его, по крайней мере, на два символа.

Вот как вы можете его реализовать:

boolean matches(String singleWord) {
    int from  = singleWord.indexOf('r');
    int to = singleWord.lastIndexOf('r');
    if (from < 0 || from == to) return false;
    String sub = singleWord.substring(from+1, to);
    return (sub.length() - sub.replaceAll("[aeiou]", "").length()) == 2;
}

Вот как это работает шаг за шагом, используя в качестве примера слово "roadster":

  • from = 0, to = 7
  • sub = "oadste"; длина 6
  • sub после замены - "dst"; длина 3
  • Выражение (6 - 3) == 2 равно 3, а не 2, поэтому возвращается false.

EDIT: последовательность должна содержать ровно две гласные, без промежуточных 'r'.

Это делает проблему немного другой, потому что трюк с первым и последним индексом больше не применяется. Однако регулярное выражение для соответствия желаемой последовательности может быть построено относительно легко - вот оно:

"r[^raeiou]*[aeiou][^raeiou]*[aeiou][^raeiou]*r"

Чтобы понять это регулярное выражение, все, что вам нужно знать, это то, что [...] соответствует любому символу внутри скобок, [^...] соответствует любому символу, кроме тех, что указаны в скобках, и * соответствует предыдущему подвыражению ноль или более раз,

Выражение длинное, но оно состоит из тривиальных частей. Он соответствует следующим:

  • Начальный r
  • Нуль или более негласных, кроме r
  • Первый гласный
  • Нуль или более негласных, кроме r
  • Второй гласный
  • Нуль или более негласных, кроме r
  • Закрытие r

Вот простая реализация:

boolean matches(String singleWord) {
    return singleWord
        .replaceAll("r[^raeiou]*[aeiou][^raeiou]*[aeiou][^raeiou]*r", "")
        .length() != singleWord.length();
}
  • 0
    вау спасибо! Единственное, что "roadster" должен возвращать ложь, так как между двумя r есть три гласных
  • 0
    я думаю, это просто вопрос изменения (sub.length() - sub.replaceAll("[aeiou]", "").length()) >= 2; to (sub.length() - sub.replaceAll("[aeiou]", "").length()) == 2;
Показать ещё 7 комментариев
2

Вы можете использовать регулярное выражение:

public static boolean matches(final String singleWord) {
    return singleWord.matches(".*r([^aeiour]*[aeiou]){2}[^aeiour]*r.*");
}

Вот тестовый код:

for (String word: "roar soccer roster reader rarar".split(" "))
    System.out.println(word+":"+matches(word));

И вот вывод:

roar:true
soccer:false
roster:true
reader:false
rarar:false
2

Вы также можете использовать регулярное выражение:

java.util.regex.Pattern.matches("\w*r\w*([aeiou]\w*){2}r\w*", "roar soccer roster reader");
  • 2
    Это не работает, если между rs есть не-гласный. Я бы использовал что-то вроде \w*r\w*([aeiou]\w*){2}r\w*
  • 0
    Да, вы правы, но мое знание регулярных выражений - это катастрофа. Я должен изучить эту тему
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню