代码之家  ›  专栏  ›  技术社区  ›  ryeguy

如何正确地给单词加前缀“a”和“an”?

  •  89
  • ryeguy  · 技术社区  · 15 年前

    我有一个.NET应用程序,在该应用程序中,给定一个名词,我希望它正确地在该词前面加上“a”或“an”。我该怎么做?

    在你认为答案是简单地检查第一个字母是否是元音之前,先考虑下列短语:

    • 一个诚实的错误
    • 二手车
    23 回复  |  直到 9 年前
        1
  •  128
  •   Eamon Nerbonne    10 年前
    1. 下载维基百科
    2. 解压它,然后编写一个只输出文章文本的快速过滤程序(下载通常是XML格式,以及非文章元数据)。
    3. 查找(n)的所有实例…并在下面的单词及其所有前缀上创建索引(您可以为此使用简单的后缀)。这应该是区分大小写的,你需要一个最长的单词长度-15个字母?
    4. (可选)丢弃所有出现少于5次或“a”与“an”达到少于2/3多数的前缀(或其他阈值-在此处调整)。最好保留空前缀,以避免出现角情况。
    5. 您可以通过放弃父级共享相同“a”或“an”批注的所有前缀来优化前缀数据库。
    6. 在确定是使用“a”还是“an”时,找到最长的匹配前缀,并跟随其前导。如果您没有放弃步骤4中的空前缀,那么将 总是 为匹配前缀(即空前缀),否则可能需要完全不匹配字符串的特殊情况(此类输入应该非常罕见)。

    你可能不会比这更好——而且它肯定会打败大多数基于规则的系统。

    编辑: 我已经 implemented this in JS/C# . 你可以 try it in your browser 或者下载它使用的小型、可重用的JavaScript实现。.NET实现是包 AvsAn on nuget . 这些实现很简单,因此在必要时可以很容易地移植到任何其他语言。

    结果“规则”比我想象的要复杂得多:

    • 它的 出乎意料的结果 一致表决
    • 它的 诚实的决定 金银花灌木
    • 符号:它的 0800号码,或 牛至。
    • 首字母缩写词: 美国宇航局科学家,但是 国家安全局分析员; 菲亚特轿车 联邦航空局的政策。

    …这只是强调了基于规则的系统很难构建!

        2
  •  15
  •   rjmunro    15 年前

    您需要使用例外列表。我不认为所有的例外都有很好的定义,因为有时这取决于说这个词的人的口音。

    一个愚蠢的方法是要求谷歌提供两种可能性(使用其中一种搜索API)并使用最流行的:

    或:

    因此,“一个欧洲”和“一个诚实的人”是正确的版本。

        3
  •  14
  •   Anon    15 年前

    如果你能找到单词拼写的来源,比如:

    "honest":"on-ist"
    "horrible":"hawr-uh-buhl, hor-"
    

    您可以根据拼写发音字符串的第一个字符来决定。 为了提高性能,也许您可以使用这种查找来预生成异常集,并在执行期间使用那些较小的查找集。

    编辑添加:

    !!!!-我认为您可以使用这个来生成异常: http://www.speech.cs.cmu.edu/cgi-bin/cmudict

    当然,并不是所有的东西都会出现在字典中——这意味着并非所有可能的例外都会出现在例外集合中——但是在这种情况下,您可以默认为辅音的for元音/a,或者使用其他概率更大的启发式方法。

    (通过查阅CMU字典,我很高兴看到它包含了一些国家和其他一些地方的专有名词,因此它将提供“乌克兰人”、“今日美国报”、“乌拉尔人启发的绘画”等例子。)

    再次编辑以添加:CMU字典不包含常见的首字母缩略词,您必须担心那些以s、f、l、m、n、u和x开头的首字母缩略词。但是有很多首字母缩略词列表,如在维基百科中,您可以使用它们来添加到例外项中。

        4
  •  9
  •   Ahmad Farid    15 年前

    您必须手动实现并添加您想要的异常,例如,如果第一个字母是“h”,然后是“o”,例如“诚实,小时”…与之相反的是欧洲,大学,用…

        5
  •  8
  •   Community    7 年前

    由于“a”和“an”是由语音规则而不是拼写惯例决定的,我可能会这样做:

    1. 如果单词的第一个字母是辅音->'A'
    2. 如果单词的第一个字母是元音->'an'
    3. 保留例外列表(心脏、X光、房屋)作为 rjumnro says .
        6
  •  4
  •   Dan Diplo    15 年前

    你需要看看不定冠词的语法规则(英语语法中只有两个不定冠词——“a”和“an”)。你可能不同意这些听起来是正确的,但是 English grammar are very clear :

    “单词a和an不确定 文章。我们用不定数 文章A开头的单词 带有元音(a,e,i,o,u)和 词前不定冠词a 从辅音开始 其他字母)。”

    注意这是指一个元音 声音 ,而不是元音 . 例如,以“h”开头的单词,如“荣誉”或“继承人”,被视为元音,而“so”则以“an”开头,例如“见到你是一种荣誉”。以辅音开头的词的前缀是A——这就是为什么你说“二手车”而不是“二手车”——因为“二手车”有“yoose”的声音而不是“uh”的声音。

    所以,作为一个程序员,这些是要遵循的规则。你只需要找出一种方法来确定一个单词的开头是什么,而不是字母。我见过这样的例子,比如 this one in PHP 作者:Jamie Sirovich:

    function aOrAn($next_word) 
    { 
        $_an = array('hour', 'honest', 'heir', 'heirloom'); 
        $_a = array('use', 'useless', 'user'); 
        $_vowels = array('a','e','i','o','u'); 
    
        $_endings = array('ly', 'ness', 'less', 'lessly', 'ing', 'ally', 'ially'); 
        $_endings_regex = implode('|', $_endings); 
    
        $tmp = preg_match('#(.*?)(-| |$)#', $next_word, $captures); 
        $the_word = trim($captures[1]); 
        //$the_word = Format::trimString(Utils::pregGet('#(.*?)(-| |$)#', $next_word, 1)); 
    
        $_an_regex = implode('|', $_an); 
        if (preg_match("#($_an_regex)($_endings_regex)#i", $the_word)) { 
            return 'an'; 
        } 
    
        $_a_regex = implode('|', $_a); 
        if (preg_match("#($_a_regex)($_endings_regex)#i", $the_word)) { 
            return 'a'; 
        } 
    
        if (in_array(strtolower($the_word{0}), $_vowels)) { 
            return 'an';     
        } 
    
        return 'a'; 
    }
    

    创建规则,然后创建异常列表并使用它可能是最简单的。我想不会有那么多。

        7
  •  3
  •   Per Alexandersson    15 年前

    @ Nathan Long: 下载维基百科其实不是一个坏主意。不需要所有图像、视频和其他媒体。

    我用php和javascript编写了一个(蹩脚的)程序!阅读整个瑞典维基百科(或者至少是所有可以从《数学》中找到的关于数学的《阿里克利斯》,这是我的蜘蛛的开始。)

    我收集了数据库中的所有单词和内部链接,并跟踪每个单词的频率。我现在将它用作各种任务的Word数据库: *查找可以从给定字母集(包括通配符)创建的所有单词 *为瑞典语创建了一个简单的语法文件(数据库中没有的所有单词都被认为是不正确的)。

    哦,下载整个wiki大约花了一周时间,我的笔记本电脑大部分时间都在运行,连接10位。

    当你做到这一点时,记录下所有与英语不一致的事件,看看其中是否有错误。去修理它们,还给社区一些东西。

        8
  •  3
  •   user2241013    11 年前

    伙计,我知道这可能是一个已经解决了的论点,但我认为比起使用维基百科的特别语法规则来解决这个问题要容易得多,因为维基百科最多只能派生出白话语法。

    最好的解决方案,似乎是使用或触发一个基于音素的匹配下列单词,某些音素总是与“an”关联,其余的属于“a”。

    卡内基梅隆大学有一个很好的在线工具来进行这种检查。- http://www.speech.cs.cmu.edu/cgi-bin/cmudict -在125k个单词处,匹配39个音素。插入一个词提供了整个音位集,其中只有第一个很重要。

    如果该词没有出现在词典中,如“nsa”,并且全部大写,那么系统可以假定该词是首字母缩略词,并使用第一个字母根据相同的原始规则集确定要使用的不定冠词。

        9
  •  2
  •   Jan Aagaard    15 年前

    注意美国方言和英国方言之间存在差异,正如《文法女孩》在其插曲中指出的那样。 A Versus An .

    一个复杂的情况是,在英美英语中,单词发音不同。例如,某种植物的单词在美国英语中发音为erb,在英国英语中发音为药草。在极少数情况下,如果这是一个问题,请使用您所在国家或大多数读者期望的表格。

        10
  •  2
  •   Sinan Ünür    15 年前

    看看Perl的 Lingua::EN::Inflect .参见 sub _indef_article 在源代码中。

        11
  •  2
  •   Community    7 年前

    我从 Python (源于CPAN软件包语言变化)正确确定C中的元音,并将其作为问题的答案发布。 Programmatically determine whether to describe an object with a or an? .您可以看到代码段 here .

        12
  •  1
  •   Paul D. Waite    14 年前

    你能给我一本英文字典,里面有用普通字母写的单词,还有 International Phoenetic Alphabet ?

    然后用光谱学计算出单词的开头音,因此a或an是否合适?

    不确定这是否比维基百科的统计方法更容易(或更有趣)。

        13
  •  0
  •   A. L. Flanagan    15 年前

    我将使用基于规则的算法尽可能多地覆盖,然后使用异常列表。如果你想变得花哨,你可以试着从例外列表中确定一些新的“规则”。

        14
  •  0
  •   Guss    15 年前

    我只是看起来像一套试探法。它需要更复杂一点,并回答一些我从来没有得到好答案的事情,例如,你如何对待缩写(“每分钟转数”或“每分钟转数”)?我一直认为后者更有意义)。

    在讨论如何处理英语单数前缀的语言库中进行了一次快速搜索,但是如果你足够深入的话,你可能会发现一些东西。如果不是,你可以写你自己的拐点图书馆,并获得世界声誉:—)。

        15
  •  0
  •   Badfish    15 年前

    我不认为你只需要把“A/A”这样的锅炉盘填上就可以了。否则,您将以假设错误结束,如所有带有“h”的单词,继续执行“o”get“an”而不是“a”like“home”-(家?)基本上,你最终会包括英语的逻辑,或者偶尔会发现一些让你看起来很愚蠢的案例。

        16
  •  0
  •   Andrew J. Brehm    15 年前

    检查单词是以元音还是辅音开头。“u”通常是辅音和元音(“yu”),因此出于您的目的属于辅音组。

    字母“h”代表法语和英语中使用的法语单词的gottal-stop(辅音)。你可以列一个清单(事实上,包括“荣誉”、“荣誉”和“小时”可能就足够了),然后把它们算作以元音开头(因为英语不承认发音停止)。

    也把“eu”算作辅音等。

    这并不太难。

        17
  •  0
  •   Rohin    15 年前

    或的选择取决于单词的发音方式。通过观察这个词,你不一定能说出它的正确发音,如行话或缩写等。 其中一种方法是使用支持音素的字典,并使用与单词相关联的音素信息来确定是否应使用“a”或“an”。

        18
  •  0
  •   rmeador    15 年前

    我不能确定它是否有适当的信息来区分“a”和“an”,但普林斯顿大学 WordNet 数据库的存在正是为了执行类似的任务,所以我认为数据可能就在其中。它有几万个单词和几十万个单词之间的关系(IIRC;我在网站上找不到当前的统计数据)。看一看。它可以免费下载。

        19
  •  0
  •   maxwellb    15 年前

    怎样?什么时候?带上冠词的名词。以特定的形式提出要求。

    用这篇文章要名词。许多泥浆代码库将项目作为信息存储,包括:

    • 一个或多个关键字
    • 短格式
    • 长形

    关键词形式可能是“短剑生锈”。简短的形式将是“一把剑”。长剑将是“生锈的短剑”。

    你在写一个“A对A”的网络服务吗?后退一步,看看是否可以在上游进一步攻击这个漏洞。你可以建一个水坝,但除非你阻止它流动,否则它最终会溢出来。

    确定这一点有多重要,正如其他人所建议的,选择“快速但粗糙”或“昂贵但坚固”。

        20
  •  0
  •   KayEss    15 年前

    规则很简单。如果下一个单词以元音开头,则使用“an”,如果以辅音开头,则使用“a”。困难的是我们学校对元音和辅音的分类不起作用。“荣誉”中的“H”是元音,“医院”中的“H”是辅音。

    更糟糕的是,有些单词,比如“诚实”是以元音或辅音开头的,这取决于谁在说。更糟糕的是,有些单词会随着周围的单词而变化。

    这个问题仅限于你想投入多少时间和精力。你可以在几分钟内用“aeiou”作为元音在几分钟内写出一些东西,或者你可以花几个月的时间对你的目标读者进行语言分析。它们之间有大量的启发式方法,对某些发言者是正确的,而对其他人则是错误的——但由于不同的发言者对同一个词有不同的决定,所以无论你怎么做,都不可能一直都是正确的。

        21
  •  0
  •   Hot Licks    13 年前

    理想的方法是在网上找到一个能给你答案的地方,动态查询并缓存答案。你可以用几百个词来启动系统。

    (我不知道这样一个在线资源,但如果有,我不会感到惊讶。)

        22
  •  0
  •   IngisKahn    10 年前

    因此,在不下载所有互联网的情况下,一个合理的解决方案是可能的。我是这样做的:

    我记得谷歌发布了谷歌图书N-gram频率的原始数据 here . 所以我下载了“a_uuu”和“an”的2-gram文件。如果我没记错的话,大约26吉格斯。在此基础上,我制作了一个字符串列表,其中的字符串前面绝大多数都是您所期望的相反的文章(如果我们期望元音加上“an”)。我能存储的最后一组单词不到7千字节。

        23
  •  -2
  •   Daniel    15 年前

    如果下一个单词不是元音,你就用“a”?你在有元音的时候用“an”吗?

    这么说,难道你就不能做一个像“a,s,e,i,o,u”这样的正则表达式吗?然后用“an”替换它。