2009-08-17 135 views
88

我有一个.NET应用程序,在给定名词的情况下,我希望它能用“a”或“an”正确地加上前缀。我会怎么做?我如何正确地用“a”和“an”加一个词?

之前,你认为答案是简单地检查,如果第一个字母是元音,可以考虑这样的短语:

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

你还必须考虑一些缩写,这些缩写也可能导致对“a”或“an”(比如“NHL”)的一些混淆,这也会出现一个字母的声音以元音开始,但如果缩写可以发音为一个词,如“NAS设备”或“NASCAR事件” – 2009-08-17 14:41:34

+5

也请记住,使用a或a可以取决于所说英语的各种特定发音。英国和美国的草药发音就是这样一个例子。 – Eric 2009-08-17 14:49:13

+12

@Eric:的确,我最喜欢的这个例子(书呆子也是)是“SQL”。有些人称这些字母为“SQL”,有些人称它为“续集”一词。每个获得不同的“一个”或“一个”。例如这是“一个续集声明”和“这是一个S-Q-L声明” – 2009-08-17 14:56:26

回答

124
  1. 下载维基百科
  2. 将其解压缩,并编写吐出只有文章全文(下载通常是XML格式的,与文章无关的元数据太)快速过滤程序。
  3. 找到a(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。这些实现是微不足道的,所以如果需要的话,它应该很容易移植到任何其他语言。

原来的“规则”是更复杂的相当多的比我想象:

  • 意料之外的结果,但它是一个全票
  • 诚实的决定,但a金银花灌木
  • 符号:它是 0800编号或∞牛至。
  • 缩略图:这是a美国宇航局科学家,但国家安全局分析师; a菲亚特汽车,但美国联邦航空局的政策。

......这只是强调,基于规则的系统会很难建立!

+0

如果这个输出中没有名词,你肯定可以回到简单的规则引擎。 – 2009-08-17 15:06:12

+0

可以使用它作为贝叶斯方法的伟大语料库。 – user7116 2009-08-17 17:17:22

+0

当代美国英语语料库(http://www.americancorpus.org/)可能是一个比维基百科更好的单项测试选择,尽管它不是可以下载的形式。 – 2009-08-17 17:48:35

9

你必须执行手动添加你想要的例外,例如,如果第一个字母是'H',然后是'O',如诚实,小时...以及像欧洲,大学这样的相反的字符...

+0

但像“料斗”这样的词将打破这一规则... – 2009-08-18 01:49:57

+1

是啊真正的男人。我想我错了。它根本没有规则 – 2009-08-18 10:57:43

15

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

一个笨的办法是要求谷歌为两种可能性(用搜索的API的一个),并使用最流行:

或者:

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

+6

这实际上是允许使用还是这个要求被禁止? IIRC当然会这样使用。 – 2009-08-17 14:53:38

+1

@Eamon:有趣的一点。如果应用程序记录了之前搜索到的所有单词的记录,那么对于遇到的每个新单词只需要google一次?这仍然是谷歌的一个可疑的用法? – gnovice 2009-08-17 16:19:29

+2

除了显而易见的技术难题(像这样以自动方式使用搜索引擎输出是不允许的并且会被相当快速地阻止),这并不能以正确的方式解决问题 - 最坏的情况是它会重复常见的滥用的语法。 – Guss 2009-08-17 16:19:31

0

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

0

我只是看起来像一组启发式。它需要更复杂一些,并回答一些我从来没有得到好答案的东西,例如你如何处理缩写(“RPM”或“RPM”?我一直认为后者更有意义)。

在语言库上快速搜索,讨论如何处理英语单数前缀,但如果挖得够用,你可能会找到一些东西。如果没有 - 你可以随时编写自己的变形库并获得世界名气:-)。

+0

像RPM这样的缩写不是问题。正如你所说,他们可以以任何方式对待。因此解决方案很明显:忽略它们。 – 2009-08-17 14:48:26

+0

我不同意,因为这会导致前缀不一致。只是忽略它会导致“RPM”和“UGC”,这显然是错误的。 – Guss 2009-08-17 16:17:06

0

我不认为你可以只填写一些锅炉板的东西,如“一个/一个”作为一个步骤覆盖所有。否则,最终会出现假设错误,比如所有带'h'的单词由'o'继续'an'而不是像'home'一样的'a' - (一个家?)。基本上,你会最终包括英语的逻辑或偶尔发现罕见的情况,这会让你看起来很愚蠢。

0

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

字母“h”代表法语中的一个gottal(辅音)和英语中使用的法语单词。你可以列出那些(实际上包括“荣誉”,“荣誉”和“小时”可能就足够了),并将它们计为以元音开头(因为英语不识别声门停止)。

也算“欧盟”作为辅音等

这不是太困难。

8

由于“一”和“一个”是由拼音规则,而不是拼写惯例确定的,我可能会做这样的:

  1. 如果单词的第一个字母是辅音 - >“一'
  2. 如果该单词的第一个字母是元音 - >'an'
  3. 保留例外列表(心脏,x光片,房子)为rjumnro says
2

请注意,美国和英国方言之间存在差异,正如语法女孩在她的剧集A Versus An中指出的那样。

一个复杂因素是当英语和美式英语中的单词发音不同时。例如,某种植物的词在美国英语中是“erb”,在英式英语中是“herb”。在出现这种问题的罕见情况下,请使用您的国家或大多数读者预期的表格。

14

如果你能找到单词拼写的字的发音源,如:

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

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

编辑补充:

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

并非一切都将在字典中,当然 - 这意味着并不是每一个可能的例外是在你的异常风集 - 但在这种情况下,你可以只默认为一个元音/一个辅音,或者使用其他一些启发式更好的赔率。

(通过CMU字典,我很高兴看到它包含适用于国家和其他地方的专有名词 - 所以它将涵盖“乌克兰”,“今日美国报”,“乌拉尔风格”绘画“。)

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

+1

不能自救,但'hawr-uh-buhl'总是让我发笑。 – IllidanS4 2014-11-02 19:53:35

0

一个或一个的选择取决于发音的方式。通过查看这个单词,你不一定能说出正确的发音,例如一个术语或缩写等。 其中一种方法可以是使字典支持音素并使用与该词相关联的音素信息来确定是应该使用“a”还是“an”。

0

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

2

看看Perl的Lingua::EN::Inflect。请参阅源代码中的sub _indef_article

+0

例外情况位于inflections.t。在我看来,这份名单并不完整。 – 2009-08-18 09:15:44

-2

只要下一个单词不是元音,就使用“a”吗?每当有元音时,你就使用“an”?这样说,难道你不能只是做一个像“a \ s [a,e,i,o,u]。”的正则表达式吗?然后用“an?”代替它

+0

不,因为规则是关于元音*声音*,不是元音*字母*。 “用户”以元音开头,但发音不是。 – 2015-12-23 17:32:16

0

怎么样?时间怎么样?获得附加文章的名词。以特定形式询问它。

请求文章中的名词。许多MUD的代码库储存物品的信息包括:

  • 一个或多个关键词
  • 的简写形式
  • 一个长形

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

您正在编写“a vs an”Web服务吗?退后一步,看看你是否可以在上游进一步攻击这个泄漏。你可以建造一座大坝,但除非你阻止它流动,否则它最终会溢出。

确定这是多么重要,正如其他人所建议的那样,“快速但粗糙”或“昂贵但坚固”。

3

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

我在php和javascript(!)中编写了一个(糟糕的)程序来阅读整个瑞典维基百科(或者至少所有可以从数学文章中得到的所有aricles,这是我的蜘蛛的开始。)

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

哦,下载整个维客花了大约一周的时间,使用我的笔记本电脑大部分时间运行,连接10Mbit。

当你在它的时候,记录所有与英语语言不一致的事件,看看它们是否有错误。去解决他们的问题,并回馈给社区。

0

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

更糟糕的是,一些像“诚实”这样的词语是从元音或辅音开始的,具体取决于谁在说他们。更糟糕的是,有些单词会根据他们周围的单词对一些发言者进行更改。

问题仅限于您想投入多少时间和精力。你可以在几分钟内用'aeiou'作为元音在夫妇身上写些东西,或者花几个月时间对目标受众进行语言分析。在他们之间有大量的启发式方法,这对一些发言者来说是正确的,对另一些发言者是错误的,但是因为不同的发言者对同一个词有不同的决定因素,无论你如何做,它总是不可能是正确的它。

4

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

“单词a和an是不确定的 文章。我们使用不定冠词“ ”前面的一个元音字母(a,e,i,o,u)和 前面的不定冠词 开头,后面是一个以辅音(所有 其他字母)开头的词。

注意,这意味着一个元音声音,而不是一个元音。例如,词用无声的“H”开头,如“荣誉”或“继承人”被视为元音的这样以“an”开头 - 例如,“能见到你很荣幸”。以辅音开头的单词前面加上了 - 这就是为什么你说“二手车”而不是“二手车” “ - 因为”used“有一种”放松“的声音而不是”uhh“的声音。

因此,作为程序员,这些是遵循的规则。你只需要找出一种方法来确定一个词开始的声音,而不是什么字母。我见过如this one in PHP通过贾米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'; 
} 

这可能比较容易创建规则,然后创建例外列表,并使用它。我不认为会有那么多。

1

你可以得到一个英文字典,它存储了我们的常规字母表中的文字和International Phoenetic Alphabet

然后用这个词来确定单词的开始声音,从而判断“a”或“an”是否合适?

不知道这是否会比统计维基百科方法更容易(或尽可能多的乐趣)。

0

理想的方法是找到能够给你答案的在线位置,动态查询它们并缓存答案。初学者可以用几百字来填充系统。

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

3

男人,我意识到这可能是一个稳定的说法,但我认为它可以比使用来自维基百科的特别语法规则更容易解决,这最多可以导出本地语法。

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

卡内基梅隆大学有一个伟大的在线工具,用于这些类型的检查 - http://www.speech.cs.cmu.edu/cgi-bin/cmudict - 和125k词与匹配的39个音素。插入一个单词可以提供整个音素组,其中只有第一个音素很重要。

如果单词没有出现在字典中,如“NSA”,并且全部大写,那么系统可以假定该单词是首字母缩写词,并使用第一个字母来确定基于相同的无限定文章原始规则集。

+0

在资源经济方面,这是最好的答案,我不明白为什么这会比提出的更多的数据密集型方法更糟糕。 – 2015-05-20 08:26:27

0

因此,一个合理的解决方案是可能的,而无需下载所有的互联网。以下是我所做的:

我记得Google发布了Google Books N-Gram频率here的原始数据。所以我下载了“a_”和“an”的2克文件。如果我记得正确的话,大约有26场演出。从那里我产生了一个字符串列表,他们在绝大多数前面加上了你期望的相反的文章(如果我们期望元音采用“an”)。那是我能够存储在7千字节以内的最后一个单词列表。

相关问题