当前位置:  开发笔记 > 编程语言 > 正文

检测单词中的音节

如何解决《检测单词中的音节》经验,为你挑选了7个好方法。

我需要找到一种相当有效的方法来检测单词中的音节.例如,

隐形 - > in-vi-sib-le

可以使用一些音节化规则:

V CV VC CVC CCV CCCV CVCC

*其中V是元音,C是辅音.例如,

发音(5 Pro-nun-ci-a-tion; CV-CVC-CV-V-CVC)

我尝试过很少的方法,其中包括使用正则表达式(只有你想要计算音节才有用)或硬编码规则定义(证明效率非常低效的强力方法),最后使用有限状态自动机(没有任何有用的结果).

我的应用程序的目的是创建一个给定语言的所有音节的字典.该词典稍后将用于拼写检查应用程序(使用贝叶斯分类器)和文本到语音合成.

如果除了我之前的方法之外,我可以提供另一种方法来解决这个问题.

我在Java工作,但C/C++,C#,Python,Perl ......中的任何提示都适合我.



1> jason..:

为了连字,请阅读有关此问题的TeX方法.特别参见Frank Liang的论文论文, 由Com-put-er提供的Word Hy-phen-a-tion.他的算法非常准确,然后包含一个小例外字典,用于算法不起作用的情况.


我喜欢你引用了关于这个主题的论文论文,它对原始海报有点暗示,这可能不是一个简单的问题.
请注意,TeX算法用于查找合法的连字点,这与音节分区不完全相同.确实,连字点落在音节分区上,但并非所有音节分区都是有效的连字点.例如,连字符(通常)不在单词的任何一个字母或两个字母内使用.我也相信TeX模式被调整为用于假阳性的假阴性(从不将连字符放在不属于它的地方,即使这意味着缺少一些合理的连字机会).

2> 小智..:

我偶然发现了这个页面,寻找同样的东西,并在这里找到了梁文的一些实现:https: //github.com/mnater/hyphenator

除非你喜欢阅读60页的论文,而不是为非独特的问题调整免费的可用代码.:)



3> hoju..:

这是使用NLTK的解决方案:

from nltk.corpus import cmudict
d = cmudict.dict()
def nsyl(word):
  return [len(list(y for y in x if y[-1].isdigit())) for x in d[word.lower()]] 


你会建议作为不在该语料库中的单词的后备?
@Pureferret [cmudict](http://www.speech.cs.cmu.edu/cgi-bin/cmudict)是北美英语单词的发音字典.它将单词分成音素,音素短于音节(例如,'cat'这个单词被分成三个音素:K-AE-T).但是元音也有一个"压力标记":0,1或2,取决于单词的发音(因此'cat'中的AE变为AE1).答案中的代码计算应力标记,从而计算元音的数量 - 这有效地给出了音节的数量(注意在OP的例子中每个音节只有一个元音).

4> Joe Basirico..:

我正在尝试解决这个问题,这个程序将计算一段文本的flesch-kincaid和flesch读数.我的算法使用了我在本网站上找到的内容:http://www.howmanysyllables.com/howtocountsyllables.html,它变得相当接近.它仍然在像隐形和连字符这样复杂的单词上遇到麻烦,但我发现它可以用于我的目的.

它具有易于实施的优点.我发现"es"既可以是音节也可以不是.这是一场赌博,但我决定删除算法中的es.

private int CountSyllables(string word)
    {
        char[] vowels = { 'a', 'e', 'i', 'o', 'u', 'y' };
        string currentWord = word;
        int numVowels = 0;
        bool lastWasVowel = false;
        foreach (char wc in currentWord)
        {
            bool foundVowel = false;
            foreach (char v in vowels)
            {
                //don't count diphthongs
                if (v == wc && lastWasVowel)
                {
                    foundVowel = true;
                    lastWasVowel = true;
                    break;
                }
                else if (v == wc && !lastWasVowel)
                {
                    numVowels++;
                    foundVowel = true;
                    lastWasVowel = true;
                    break;
                }
            }

            //if full cycle and no vowel found, set lastWasVowel to false;
            if (!foundVowel)
                lastWasVowel = false;
        }
        //remove es, it's _usually? silent
        if (currentWord.Length > 2 && 
            currentWord.Substring(currentWord.Length - 2) == "es")
            numVowels--;
        // remove silent e
        else if (currentWord.Length > 1 &&
            currentWord.Substring(currentWord.Length - 1) == "e")
            numVowels--;

        return numVowels;
    }



5> Chris..:

这是一个特别困难的问题,LaTeX连字算法无法完全解决这个问题.一些可用的方法和所涉及的挑战的一个很好的总结可以在文章评估英语自动音节化算法(Marchand,Adsett和Damper 2007)中找到.



6> 小智..:

感谢Joe Basirico,在C#中分享快速而肮脏的实现.我使用过大型库,它们可以工作,但它们通常有点慢,对于快速项目,你的方法运行正常.

以下是Java中的代码以及测试用例:

public static int countSyllables(String word)
{
    char[] vowels = { 'a', 'e', 'i', 'o', 'u', 'y' };
    char[] currentWord = word.toCharArray();
    int numVowels = 0;
    boolean lastWasVowel = false;
    for (char wc : currentWord) {
        boolean foundVowel = false;
        for (char v : vowels)
        {
            //don't count diphthongs
            if ((v == wc) && lastWasVowel)
            {
                foundVowel = true;
                lastWasVowel = true;
                break;
            }
            else if (v == wc && !lastWasVowel)
            {
                numVowels++;
                foundVowel = true;
                lastWasVowel = true;
                break;
            }
        }
        // If full cycle and no vowel found, set lastWasVowel to false;
        if (!foundVowel)
            lastWasVowel = false;
    }
    // Remove es, it's _usually? silent
    if (word.length() > 2 && 
            word.substring(word.length() - 2) == "es")
        numVowels--;
    // remove silent e
    else if (word.length() > 1 &&
            word.substring(word.length() - 1) == "e")
        numVowels--;
    return numVowels;
}

public static void main(String[] args) {
    String txt = "what";
    System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
    txt = "super";
    System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
    txt = "Maryland";
    System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
    txt = "American";
    System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
    txt = "disenfranchized";
    System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
    txt = "Sophia";
    System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
}

结果如预期的那样(它对Flesch-Kincaid来说足够好):

txt=what countSyllables=1
txt=super countSyllables=2
txt=Maryland countSyllables=3
txt=American countSyllables=3
txt=disenfranchized countSyllables=5
txt=Sophia countSyllables=2



7> Tersosauros..:

撞到@Tihamer和@ joe-basirico.非常有用的功能,不完美,但适用于大多数中小型项目.Joe,我用Python重写了你的代码实现:

def countSyllables(word):
    vowels = "aeiouy"
    numVowels = 0
    lastWasVowel = False
    for wc in word:
        foundVowel = False
        for v in vowels:
            if v == wc:
                if not lastWasVowel: numVowels+=1   #don't count diphthongs
                foundVowel = lastWasVowel = True
                        break
        if not foundVowel:  #If full cycle and no vowel found, set lastWasVowel to false
            lastWasVowel = False
    if len(word) > 2 and word[-2:] == "es": #Remove es - it's "usually" silent (?)
        numVowels-=1
    elif len(word) > 1 and word[-1:] == "e":    #remove silent e
        numVowels-=1
    return numVowels

希望有人觉得这很有用!

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有