Java - 根据规范编写音节计数器

时间:2012-02-05 23:20:01

标签: java string methods

音节规格:

每组相邻的元音(a,e,i,o,u,y)计为一个音节(例如,“real”中的“ea”贡献一个音节,但“e ... a”在“皇家”中算作两个音节)。但是,单词末尾的“e”不算作音节。此外,每个单词至少有一个音节,即使之前的规则计数为零。

我的countSyllables方法:

public int countSyllables(String word) {
    int count = 0;
    word = word.toLowerCase();
    for (int i = 0; i < word.length(); i++) {
        if (word.charAt(i) == '\"' || word.charAt(i) == '\'' || word.charAt(i) == '-' || word.charAt(i) == ',' || word.charAt(i) == ')' || word.charAt(i) == '(') {
            word = word.substring(0,i)+word.substring(i+1, word.length());
        }
    }
    boolean isPrevVowel = false;
    for (int j = 0; j < word.length(); j++) {
        if (word.contains("a") || word.contains("e") || word.contains("i") || word.contains("o") || word.contains("u")) {
            if (isVowel(word.charAt(j)) && !((word.charAt(j) == 'e') && (j == word.length()-1))) {
                if (isPrevVowel == false) {
                    count++;
                    isPrevVowel = true;
                }
            } else {
                isPrevVowel = false;
            }
        } else {
            count++;
            break;
        }
    }
    return count;
}

确定字母是否为元音的isVowel方法:

public boolean isVowel(char c) {
        if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
            return true;
        } else {
            return false;
        }
    }

根据一位同事的说法,这在this text上使用时应该会产生528个音节,但我似乎可以将其与之相提并论,我不知道哪个是正确的。请帮助我将我的方法开发成正确的算法或帮助显示这是正确的。谢谢。

7 个答案:

答案 0 :(得分:3)

问题之一可能是您在输入上调用了lover case方法,但是您没有分配它。

所以如果你改变了

 word.toLowerCase();

word =  word.toLowerCase();

肯定会有所帮助。

答案 1 :(得分:0)

我强烈建议您完全使用Java的String API。例如,考虑String.split(String regex):

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split%28java.lang.String%29

这将使用String和正则表达式,然后使用正则表达式作为分隔符返回所有子字符串的数组。如果你使正则表达式匹配所有辅音或空格,那么你将得到一个字符串数组,这些字符串是空的(因此不代表辅音)或元音序列(它代表一个辅音)。算上后者,你就会有一个解决方案。

另一个利用String API和正则表达式的替代方法是replaceAll:

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29

在这种情况下,你需要一个正则表达式,它采用[可选任何不是元音的形式] [一个或多个元音] [可选任何不是元音的东西]的形式。在String上运行此正则表达式,并将其替换为单个字符(例如“1”)。最终结果是每个音节将被单个字符替换。然后你需要做的就是String.length(),你就会知道你有多少个音节。

根据您的解决方案的要求,这些可能无效。如果这是与算法设计相关的作业问题,这几乎肯定不是首选答案,但它确实具有简洁的优点,并且充分利用了内置(因此高度优化)的Java API。

答案 2 :(得分:0)

对于某些正则表达式,这应该很容易实现:

Pattern p = Pattern.compile("[aeiouy]+?\w*?[^e]");
String[] result = p.split(WHAT_EVER_THE_INPUT_IS);
result.length

请注意,它未经测试。

答案 3 :(得分:0)

不是一个直接的答案(如果我认为它是建设性的,我会给你一个,我的计数在上一次尝试中大约是238)但是我会给你一些提示,这将是创造答案的基础:

  1. 划分你的问题:读取行,然后将行分成单词,然后计算每个单词的音节。后记,计算所有行。
  2. 考虑事物的顺序:首先找到所有的音节,并通过“走”字来计算每个音节。然后考虑特殊情况。
  3. 在设计过程中,使用调试器逐步执行代码。您可能会犯toUpperCase()方法等常见错误。更好地发现这些错误,没有人会在第一时间创建完美的代码。
  4. 打印到控制台(高级用户使用日志并在最终程序中保留沉默的日志行)。确保使用注释标记println并将其从最终实现中删除。打印行号和音节计数等内容,以便您可以直观地将它们与文本进行比较。
  5. 如果你有一点高级,你可以使用Matcher.find(正则表达式)使用Pattern来找到音节。正则表达式是难以掌握的野兽。一个常见的错误就是让他们一气呵成。
  6. 这样您就可以快速扫描文本。您很快就会发现的一件事是您必须处理文本中的数字。所以你需要检查单词是否实际上是一个单词,否则,根据你的规则,它至少会有一个单独的音节。

    如果你有重复的感觉,比如使用同一组字符的isVowelString.contains()方法,你可能会做错事。源代码中的重复是代码味道。

    使用正则表达式,我计算了大约238(第4次),但我还没有真正检查过每个音节(当然)。

    1 14
    2 17
    3 17
    4 15
    5 15
    6 14
    7 16
    8 19
    9 17
    10 17
    11 16
    12 19
    13 18
    14 15
    15 18
    16 15
    17 16
    18 17
    19 16
    20 17
    21 17
    22 19
    23 17
    24 16
    25 17
    26 17
    27 16
    28 17
    29 15
    30 17
    31 19
    32 23
    33 0
    
     --- total --- 
    538
    

答案 4 :(得分:0)

我刚刚发明了一种用Java计算音节的新方法。

我的新图书馆The Lawrence Style Checker可以在这里查看:https://github.com/troywatson/Lawrence-Style-Checker

我使用我的程序计算了每个单词的音节,并在此处显示结果:http://pastebin.com/LyiBTcbb

用我的字典方法计算音节我得到了:总共528个音节。

这是提问者给出的正确音节数的确切数字。然而,由于以下原因,我仍然对此数字提出异议:

执行率:99.4%正确

字错:2/337字

单词错误和错误的音节计数:{resinous:4,aardwolf:3}

这是我的代码:

    Lawrence lawrence = new Lawrence();

    // Turn the text into an array of sentences.
    String sentences = ""
    String[] sentences2 = sentences.split("(?<=[a-z])\\.\\s+");

    int count = 0;

    for (String sentence : sentences2) {
        sentence = sentence.replace("-", " "); // split double words
        for (String word : sentence.split(" ")) {

            // Get rid of punctuation marks and spaces.
            word = lawrence.cleanWord(word);

            // If the word is null, skip it.
            if (word.length() < 1)
                continue;

            // Print out the word and it's syllable on one line.
            System.out.print(word + ",");
            System.out.println(lawrence.getSyllable(word));
            count += lawrence.getSyllable(word);
        }
    }
    System.out.println(count);

BAM!

答案 5 :(得分:0)

select c.DateCurrent, sum(i.ItemCost * c.quantity) as Bill
from CustomerOrder c inner join
    item i
    on i.ItemId = c.ItemId  
where c.datecurrent >= '2017-04-13'
group by grouping sets ( (c.DateCurrent), () );

另一个实现可以在下面的pastebin链接中找到: https://pastebin.com/q6rdyaEd

答案 6 :(得分:-1)

这是我计算音节的实现

protected int countSyllables(String word)
{
    // getNumSyllables method in BasicDocument (module 1) and 
    // EfficientDocument (module 2).
    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();
    return syllables;
}

它适用于我。