如何为单词加上“ a”和“ an”前缀?


92

我有一个.NET应用程序,在其中给定了一个名词,我希望它为该单词加上“ a”或“ an”前缀。我该怎么做?

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

  • 一个诚实的错误
  • 二手车

4
您还必须考虑缩写,这也可能导致对“ a”或“ an”(例如“ NHL”)的某些混淆,后者也会出现字母的声音以元音开头,但是如果可以将缩写发音为诸如作为“ NAS设备”或“ NASCAR事件”
JB King

5
还请记住,a或an的使用可能取决于所讲英语的特定发音。草药的英式和美式发音就是这样的例子。
埃里克

12
@Eric:的确,对此我最喜欢的示例(也很讨厌)是“ SQL”。有些人说字母“ SQL”,有些人说它像“续集”一词。每个都获得不同的“ a”或“ an”。例如,它是“续集语句”,而“这是SQL语句”
Binary Worrier

更加困难的是,同一英语方言中的意见甚至不同!因此,例如,官方(英国)英语告诉我们“旅馆”是正确的结构,但是大多数人在日常对话中都会使用“旅馆”。如果您写一个,对我们其他人将非常有用!
h4xxr

啊...“有抱负的H”。我生动地记得我第一次接触它。一本名为《历史协会》的二年级社会研究书,一本关于殖民地威廉斯堡的书。
鲍勃·考夫曼

Answers:


137
  1. 下载维基百科
  2. 将其解压缩并编写一个快速过滤程序,该程序仅显示文章文本(下载内容通常为XML格式,也包含非文章元数据)。
  3. 查找a(n)....的所有实例,并在以下单词及其所有前缀上建立索引(您可以为此使用简单的后缀)。这应该区分大小写,并且您需要最大字长-15个字母?
  4. (可选)丢弃所有出现次数少于5次或“ a”对“ an”的投票少于2/3的前缀(或其他阈值-在此处进行调整)的所有前缀。最好保留空前缀,以避免出现极端情况。
  5. 您可以通过舍弃其父项共享相同的“ a”或“ an”注释的所有那些前缀来优化您的前缀数据库。
  6. 在确定使用“ A”还是“ AN”时,找到最长的匹配前缀,并遵循其前缀。如果您没有在步骤4中丢弃空前缀,那么总会有一个匹配的前缀(即空前缀),否则,对于完全不匹配的字符串,您可能需要特殊的情况(这种输入很少见) 。

您可能没有比这更好的了-它肯定会击败大多数基于规则的系统。

编辑:我已经在JS / C#中实现了这一点。您可以在浏览器中进行尝试,或下载其使用的小型可重复使用的javascript实现。.NET实现是AvsAn在nuget上打包的。这些实现是微不足道的,因此在必要时应易于移植到任何其他语言。

原来,“规则”比我想象的要复杂得多:

  • 出乎意料的结果,但却一致的投票
  • 这是一个诚实的决定,但一个金银花灌木
  • 符号:这是一个 0800的数字,或者牛至 ∞。
  • 缩略语:这是一个美国航空航天局的科学家,而是一个国家安全局分析师; 一辆菲亚特汽车,但联邦航空管理局的政策。

...这恰恰说明基于规则的系统构建起来很棘手!


而且,如果此输出中缺少名词,那么您当然可以使用简单的规则引擎。
约翰·费舍尔2009年

26
鉴于Wikipedia下载已解压缩到(当前)2.8 TB,如果使用此方法的任何人都公开发布结果数据,那就太好了,因此不必重复太多该过程。
内森·朗

10
这个答案并不完全是认真的,但我已经做了类似的事情,而带有原始wikimarkup的Wikipedia的.xml文件仅约为40GB(最新的总是更大一点),而不是2.8TB-全部集中在一个文件中-不要下载扩展的.html版本或任何图像,也许就是2.8TB的版本?无论如何,只要您不对标记挑剔,解析实际上是很可行的。
2009年

1
它是我能想到的最大的易于获得的,最新的自然语言数据集之一。但是,当然,任何其他数据源也可以-毕竟,该算法不依赖于Wikipedia。您可以在home.nerbonne.org/A-vs-An我的博客
Eamon Nerbonne 2013年

1
我是超越这个解决方案印象深刻。老实说,我认为这比完整下载Wikipedia容易得多干得好,先生。+1
Kehlan Krumme 2014年

15

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

一种愚蠢的方法是要求Google提供两种可能性(使用一种搜索API)并使用最受欢迎的一种:

要么:

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


6
那是实际允许的使用还是要求禁止使用?定期这样的使用肯定会受到IIRC的反对。
Eamon Nerbonne 09年

1
@Eamon:有趣的一点。如果应用程序保留了以前搜索过的所有单词的记录,那么对于遇到的每个新单词,只需对它进行一次Google搜索,该怎么办?谷歌的使用方式仍然会令人怀疑吗?
gnovice

2
除了明显的技术难题(不允许以这种自动化方式使用搜索引擎输出,而且很快会阻止其使用)之外,这不能以正确的方式解决问题-更糟的是,它会重复出现常见的误用句法。
格斯,

6
最糟糕的是?有一个非常强烈的论点是,复制“常见误用”正是自然语言系统应努力争取的。请参阅《思考龙虾》中大卫·福斯特·华莱士(David Foster Wallace)的文章“权威与美国人的用法” 。有比Google更好的语料库,但这是另一个问题。
罗伯特·罗斯尼

2
“旅馆”和“女英雄”在我看来都是对的。我想您是从有点鸡肋的口音来看的。不同的口音意味着其中某些单词没有正确的答案。
rjmunro

15

如果您可以找到单词发音的单词拼写来源,例如:

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

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

编辑添加:

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

当然,并不是所有的东西都在字典中-这意味着并不是所有可能的异常都会出现在您的异常集中-但是在这种情况下,您可以默认为元音为a /辅音为a或使用其他具有更好几率的启发式方法。

(通过查看CMU词典,我很高兴看到它包含了国家和其他地方的专有名词-因此它将提供“乌克兰语”,“今日美国报”,“乌拉尔风格的绘画”等示例。)

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


2
不能帮助自己,但hawr-uh-buhl总是让我发笑。
IllidanS4希望莫妮卡回到2014年


8

由于“ a”和“ an”是由语音规则而不是拼写约定确定的,所以我可能会这样做:

  1. 如果单词的首字母是辅音->'a'
  2. 如果单词的第一个字母是元音->'an'
  3. rjumnro所说,保留一份例外清单(心脏,X光片,房屋)。

5

您需要查看不定冠词的语法规则(英语语法中只有两个不定冠词-“ a”和“ an”。您可能不同意这些听起来正确,但是英语语法的规则非常明确

“ a和an是不定冠词。我们使用不定冠词a以元音开头(a,e,i,o,u),而不定冠词a以辅音开头(所有其他字母)。”

注意,这意味着一个元音的声音,而不是一个元音字母。例如,以无声的“ h”开头的单词(例如“ honour”或“ heir”)被视为元音,因此以“ an”开头-例如,“很高兴认识您”。以辅音开头的单词以-开头,这就是为什么您说“二手车”而不是“二手车”的原因-因为“二手”的声音是“洋洋”而不是“呃”。

因此,作为程序员,这些是要遵循的规则。您只需要确定一种方法即可确定单词的发音,而不是字母。我已经看到了这样的示例,例如Jaimie Sirovich 在PHP中撰写的示例:

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'; 
}

创建规则然后创建例外列表并使用它可能是最简单的。我不认为会有那么多。


4

伙计,我意识到这可能是一个确定的论点,但我认为它比使用Wikipedia的即席语法规则充其量要容易得多,后者最多只能得出白话语法。

最好的解决方案似乎是使用a或触发器来实现后续单词的基于音素的匹配,其中某些音素始终与“ an”相关联,而其余音素则与“ a”相关。

卡内基梅隆大学拥有一个出色的在线工具,可以进行此类检查-http : //www.speech.cs.cmu.edu/cgi-bin/cmudict-并以125k的单词数和39个音素相匹配。插入单词会提供整个语音组,其中只有第一个很重要。

如果单词未出现在字典中,例如“ NSA”,并且全部大写,则系统可以假定该单词为首字母缩写词,并根据相同的原始规则集使用第一个字母来确定要使用哪个不定冠词。


1
就资源经济而言,这是最好的答案,我不明白为什么这样做的结果会比提议的数据密集型方法差很多。
Chthonic项目

3

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

我用php和javascript(!)编写了一个(糟糕的)程序,以阅读整个瑞典语维基百科(或至少从有关数学的文集中可以找到的所有小书,这就是我的蜘蛛的开始。)

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

哦,使用我的笔记本电脑大部分时间都是在10Mbit的连接下运行的,下载整个Wiki大约花了一个星期的时间。

当您使用它时,请记录所有与英语不一致的情况,并查看其中是否有错误。修复它们并回馈社区。


2

请注意,正如“语法女孩”在她的情节A对战方言中指出的那样,美国和英国方言之间存在差异。

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



2

我已经从Python移植了一个函数(最初是从CPAN包Lingua-EN-Inflect来的),该函数正确地确定了C#中的元音,并将其发布为问题的答案。您可以在此处查看代码段。


1

您能得到一个英语词典,该词典存储用我们的常规字母和国际拼音字母写的单词吗?

然后使用语音识别法找出单词的开头音,因此“ a”或“ an”是否合适?

不知道这是否真的比统计Wikipedia方法容易(或那么有趣)。


0

我将使用基于规则的算法来覆盖尽可能多的内容,然后使用例外列表。如果您想花哨的话,可以尝试从例外列表中确定一些新的“规则”。


0

我只是看起来像一组启发式方法。它需要更复杂一些,并回答一些我从来没有很好回答过的事情,例如您如何处理缩写(“ RPM”或“ RPM”?我一直认为后者更有意义)。

对语言库进行了快速搜索,这些语言库讨论了如何处理英文单数前缀,但是如果您对Dip进行足够的挖掘,则可能会找到一些东西。如果不是这样,您可以随时编写自己的变形库并获得世界声誉:-)。


诸如RPM之类的缩写不是问题。正如您所说,可以用任何一种方式来对待它们。因此,解决方案很明显:忽略它们。
安德鲁·布雷姆

我不同意,因为这会导致前缀不一致。只是忽略它会导致“ RPM”和“ UGC”,这显然是错误的。
古斯

0

我不认为您可以一步一步地填写一些“ a / an”样板文件。否则,您将遇到假设错误,例如所有带有“ h”的单词都以“ o”开头,而不是像“ home”之类的“ a”(家庭)?基本上,您最终会包括英语的逻辑,或者偶尔发现使您看起来很愚蠢的罕见情况。


0

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

字母“ h”代表法文和英语中使用的法文单词的总括符(辅音)。您可以列出这些名称(实际上,包括“荣誉”,“荣誉”和“小时”可能就足够了),并将它们视为以元音开头(因为英语无法识别声门)。

还要将“ eu”算作辅音等。

不太困难。


0

a或a的选择取决于单词的发音方式。通过查看单词,您不一定能说出正确的发音,例如,术语或缩写等。方法之一是拥有支持音素的字典,并使用与单词相关的音素信息来确定“ ”或“ an”。


0

我无法确定其中是否包含用于区分“ a”和“ an”的适当信息,但是普林斯顿大学的WordNet数据库正是出于类似任务目的而存在的,因此我认为数据很可能就在其中。它有成千上万个单词,所说单词之间有数十万个关系(IIRC;我在网站上找不到当前统计信息)。看看吧。可免费下载。


0

怎么样?怎么样?获取附带文章的名词。要求以特定的形式。

在文章中询问名词。许多MUD代码库将项目存储为以下信息:

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

关键字形式可能是“生锈的短剑”。缩写形式是“一把剑”。长形将是“生锈的短剑”。

您正在编写“ a vs. an” Web服务吗?退后一步,看看是否可以在上游进一步解决此泄漏问题。您可以建造一个水坝,但是除非您阻止其流动,否则最终将溢出。

确定这有多重要,并按照其他人的建议,选择“快速但粗暴”或“昂贵但坚固”。


0

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

更糟糕的是,诸如“诚实”之类的词以元音或辅音开头,取决于谁在说。更糟糕的是,某些说话者会根据周围的单词改变某些单词。

问题仅取决于您要投入多少时间和精力。您可以在几分钟之内使用“ aeiou”作为元音在一对夫妇中写一些东西,或者您可以花费数月的时间对目标受众进行语言分析。它们之间有大量的启发式方法,对于某些说话者来说是正确的,而对于另一些说话者来说则是错误的-但是由于不同的说话者对同一个单词有不同的判断力,因此无论您怎么做,都不可能一直都是正确的它。


0

理想的方法是在网上找到可以为您提供答案,动态查询它们并缓存答案的地方。您可以使用几百个单词作为启动器来启动系统。

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


0

因此,无需下载所有Internet就可以实现合理的解决方案。这是我所做的:

我记得,谷歌公布了他们对谷歌图书的N-gram频率的原始数据在这里。因此,我下载了“ a_”和“ an”的2克文件。如果我没记错的话,大约是26场演出。据此,我生成了一个字符串列表,在这些字符串中,绝大多数都是您所期望的相反文章(如果我们希望元音带有“ an”)。我能够存储的最终单词列表不到7 KB。


-2

只要下一个单词不是元音,就使用“ a”吗?当有元音时,您使用“ an”吗?

这么说,您难道不就做一个正则表达式,例如“ a \ s [a,e,i,o,u]。*”吗?然后将其替换为“ an”?


不,因为规则是约元音的声音,而不是元音字母。“用户”以元音开头,但发音不是。
Joris Groosman 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.