Я пытаюсь найти из предложения слова, которые содержат две гласные между двумя 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);
}
Вы можете сделать это, используя простой алгоритм без циклов:
'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"
; длина 6sub
после замены - "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();
}
Вы можете использовать регулярное выражение:
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
Вы также можете использовать регулярное выражение:
java.util.regex.Pattern.matches("\w*r\w*([aeiou]\w*){2}r\w*", "roar soccer roster reader");
\w*r\w*([aeiou]\w*){2}r\w*
"roadster"
должен возвращать ложь, так как между двумяr
есть три гласных(sub.length() - sub.replaceAll("[aeiou]", "").length()) >= 2;
to(sub.length() - sub.replaceAll("[aeiou]", "").length()) == 2;