如何使用正则表达式和Java计算文本中的音节
我将文本作为如何使用正则表达式和Java计算文本中的音节,java,arrays,regex,string,Java,Arrays,Regex,String,我将文本作为字符串,需要计算每个单词的音节数。我尝试将所有文本拆分为单词数组,然后分别处理每个单词。我用了正则表达式。但音节的模式并没有发挥应有的作用。请建议如何更改它以计算正确的音节数。我的初始代码 public int getNumSyllables() { String[] words = getText().toLowerCase().split("[a-zA-Z]+"); int count=0; List <String> tokens = new
字符串
,需要计算每个单词的音节数。我尝试将所有文本拆分为单词数组,然后分别处理每个单词。我用了正则表达式。但音节的模式并没有发挥应有的作用。请建议如何更改它以计算正确的音节数。我的初始代码
public int getNumSyllables()
{
String[] words = getText().toLowerCase().split("[a-zA-Z]+");
int count=0;
List <String> tokens = new ArrayList<String>();
for(String word: words){
tokens = Arrays.asList(word.split("[bcdfghjklmnpqrstvwxyz]*[aeiou]+[bcdfghjklmnpqrstvwxyz]*"));
count+= tokens.size();
}
return count;
}
public int getNumSyllables()
{
String[]words=getText().toLowerCase().split(“[a-zA-Z]+”);
整数计数=0;
List tokens=new ArrayList();
for(字符串字:字){
令牌=Arrays.asList(word.split(“[bcdfghjklmnpqrstvwxyz]*[aeiou]+[bcdfghjklmnpqrstvwxyz]*”);
count+=tokens.size();
}
返回计数;
}
您的线路
String[] words = getText().toLowerCase().split("[a-zA-Z]+");
正在拆分单词,只返回单词之间的空格!您希望在单词之间的空格上拆分,如下所示:
String[] words = getText().toLowerCase().split("\\s+");
这将为您提供一个单词中的多个音节和元音:
public int getNumVowels(String word) {
String regexp = "[bcdfghjklmnpqrstvwxz]*[aeiouy]+[bcdfghjklmnpqrstvwxz]*";
Pattern p = Pattern.compile(regexp);
Matcher m = p.matcher(word.toLowerCase());
int count = 0;
while (m.find()) {
count++;
}
return count;
}
您可以在字符串数组中的每个单词上调用它:
String[] words = getText().split("\\s+");
for (String word : words ) {
System.out.println("Word: " + word + ", vowels: " + getNumVowels(word));
}
更新:正如freerunner所指出的,计算音节的数量比仅仅计算元音要复杂得多。我们需要考虑像ou、ui、oo、最终的沉默e和其他可能的组合。由于我不是以英语为母语的人,我不确定正确的算法是什么。您使用的分割方法不正确。这种方法接收分离器。你需要写这样的东西:
String[] words = getText().toLowerCase().split(" ");
但是如果你想计算音节的数量,那么计算元音的数量就足够了:
String input = "text";
Set<Character> vowel = new HashSet<>();
vowel.add('a');
vowel.add('e');
vowel.add('i');
vowel.add('o');
vowel.add('u');
int count = 0;
for (char c : input.toLowerCase().toCharArray()) {
if (vowel.contains(c)){
count++;
}
}
System.out.println("count = " + count);
String input=“text”;
Set元音=新HashSet();
元音。加上('a');
元音。加上('e');
元音。加上('i');
元音。加上('o');
元音。加上('u');
整数计数=0;
for(字符c:input.toLowerCase().toCharArray()){
if(元音包含(c)){
计数++;
}
}
System.out.println(“count=“+count”);
使用user5500105的概念,我开发了以下方法来计算单词中音节的数量。这些规则是:
- 连续元音按1个音节计算。“ae”“ou”是一个音节
- Y被认为是元音
- 如果e是唯一的元音,则结尾的e被视为音节:例如:“the”是一个音节,因为结尾的“e”是唯一的元音,而“there”也是一个音节,因为“e”在结尾,单词中还有另一个元音
public int countSyllables(String word) { ArrayList<String> tokens = new ArrayList<String>(); String regexp = "[bcdfghjklmnpqrstvwxz]*[aeiouy]+[bcdfghjklmnpqrstvwxz]*"; Pattern p = Pattern.compile(regexp); Matcher m = p.matcher(word.toLowerCase()); while (m.find()) { tokens.add(m.group()); } //check if e is at last and e is not the only vowel or not if( tokens.size() > 1 && tokens.get(tokens.size()-1).equals("e") ) return tokens.size()-1; // e is at last and not the only vowel so total syllable -1 return tokens.size(); }
public int count音节(字符串词){ ArrayList标记=新的ArrayList(); 字符串regexp=“[bcdfghjklmnpqrstvwxz]*[aeiouy]+[bcdfghjklmnpqrstvwxz]*”; Pattern p=Pattern.compile(regexp); Matcher m=p.Matcher(word.toLowerCase()); while(m.find()){ 添加(m.group()); } //检查e是否是最后一个元音,e是否不是唯一的元音 if(tokens.size()>1&&tokens.get(tokens.size()-1).equals(“e”)) return tokens.size()-1;//e终于是并且不是唯一的元音,所以总音节-1 返回tokens.size(); }
- 这个问题来自UCSD的Java课程,对吗
我认为你应该为这个问题提供足够的信息,这样就不会让想要提供帮助的人感到困惑。这里我有我自己的解决方案,已经由本地项目的测试用例测试过了,也就是UCSD的OJ
你在这个问题中遗漏了一些关于音节定义的重要信息事实上,我认为这个问题的关键是如何处理
e
例如,假设存在te
的组合。如果你把一个词放在一个词的中间,当然它应该被计算成一个音节;然而,如果它在一个单词的末尾,那么在英语中,e
应该被认为是一个无声的e
,因此它不应该被认为是一个音节
就这样。我想用一些伪代码写下我的想法:
if(last character is e) {
if(it is silent e at the end of this word) {
remove the silent e;
count the rest part as regular;
} else {
count++;
} else {
count it as regular;
}
}
您可能会发现,我不仅仅使用regex来处理这个问题。事实上我已经考虑过了:这个问题真的只能用正则表达式来解决吗?我的回答是:不,我不这么认为。至少现在,根据UCSD给我们的知识,要做到这一点太难了。正则表达式是一个功能强大的工具,它可以非常快速地映射所需的字符。然而,regex缺少一些功能。再以te
为例,当regex面对teate
这样的单词时,它不会三思而后行(我只是编了这个单词作为例子)。如果我们的正则表达式模式将第一个te
算作音节,那么为什么最后一个te
不算作音节呢
同时,UCSD在作业文件中也提到了这一点:
如果你发现自己在做精神体操,用一个单一的正则表达式直接计算音节,这通常表明有一个更简单的解决方案(提示:考虑一个循环的字符——参见下面的下一个提示)。仅仅因为一段代码(例如正则表达式)更短并不意味着它总是更好
这里的提示是,您应该将这个问题与一些循环结合起来考虑,并与正则表达式相结合 好的,我现在终于应该显示我的代码了:protected int countSyllables(String word)
{
// TODO: Implement this method so that you can call it from the
// getNumSyllables method in BasicDocument (module 1) and
// EfficientDocument (module 2).
int count = 0;
word = word.toLowerCase();
if (word.charAt(word.length()-1) == 'e') {
if (silente(word)){
String newword = word.substring(0, word.length()-1);
count = count + countit(newword);
} else {
count++;
}
} else {
count = count + countit(word);
}
return count;
}
private int countit(String word) {
int count = 0;
Pattern splitter = Pattern.compile("[^aeiouy]*[aeiouy]+");
Matcher m = splitter.matcher(word);
while (m.find()) {
count++;
}
return count;
}
private boolean silente(String word) {
word = word.substring(0, word.length()-1);
Pattern yup = Pattern.compile("[aeiouy]");
Matcher m = yup.matcher(word);
if (m.find()) {
return true;
} else
return false;
}
您可能会发现,除了使用给定的方法countsyllets
,我还创建了另外两个方法countit
和silente
countit
用于计算单词内部的音节,silente
试图找出这个单词是否以无声的e
结尾。还应该注意的是,的定义不是沉默的e
。例如,<代码> <代码>应考虑<代码>不沉默e < /代码>,而<代码> ATE 被认为是代码>静默e>代码>
下面是我的代码已经通过测试的状态,来自本地测试用例和UCSD的OJ:
根据OJ的测试结果:
附言:应该可以
public int getNumSyllables()
{
return getSyllables(getTokens("[a-zA-Z]+"));
}
protected List<String> getWordTokens(String word,String pattern)
{
ArrayList<String> tokens = new ArrayList<String>();
Pattern tokSplitter = Pattern.compile(pattern);
Matcher m = tokSplitter.matcher(word);
while (m.find()) {
tokens.add(m.group());
}
return tokens;
}
private int getSyllables(List<String> tokens)
{
int count=0;
for(String word : tokens)
if(word.toLowerCase().endsWith("e") && getWordTokens(word.toLowerCase().substring(0, word.length()-1), "[aeiouy]+").size() > 0)
count+=getWordTokens(word.toLowerCase().substring(0, word.length()-1), "[aeiouy]+").size();
else
count+=getWordTokens(word.toLowerCase(), "[aeiouy]+").size();
return count;
}
public static int syllables(String s) {
final Pattern p = Pattern.compile("([ayeiou]+)");
final String lowerCase = s.toLowerCase();
final Matcher m = p.matcher(lowerCase);
int count = 0;
while (m.find())
count++;
if (lowerCase.endsWith("e"))
count--;
return count < 0 ? 1 : count;
}
int syllables = 0;
word = word.toLowerCase();
if(word.contains("the ")){
syllables ++;
}
String[] split = word.split("e!$|e[?]$|e,|e |e[),]|e$");
ArrayList<String> tokens = new ArrayList<String>();
Pattern tokSplitter = Pattern.compile("[aeiouy]+");
for (int i = 0; i < split.length; i++) {
String s = split[i];
Matcher m = tokSplitter.matcher(s);
while (m.find()) {
tokens.add(m.group());
}
}
syllables += tokens.size();