我怎样才能正确的前缀一个单词“一”和“一个”?

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

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

  • 一个诚实的错误
  • 一辆二手车
  1. 下载维基百科
  2. 解压缩并编写一个快速筛选程序,只扫出文章文本(下载通常是XML格式,还有非文章元数据)。
  3. find一个(n)….的所有实例,并在下面的单词和所有的前缀(你可以使用一个简单的后缀为这个)做一个索引。 这应该区分大小写,你需要一个最大的字长 – 15个字母?
  4. (可选)丢弃发生less于5次的所有前缀,或者“a”与“an”达到less于2/3的多数(或者其他一些阈值 – 在此调整)的前缀。 最好保留空白的前缀,以避免angular落案件。
  5. 您可以优化您的前缀数据库,通过丢弃所有那些母公司拥有相同“a”或“an”注释的前缀。
  6. 在确定是使用“A”还是“AN”查找最长的匹配前缀时, 如果你没有在第4步中丢弃空的前缀,那么总是会有一个匹配的前缀(即空前缀),否则你可能需要一个特殊的情况下完全非匹配的string(这样的input应该是非常罕见的) 。

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

编辑:我已经在JS / C#中实现了这一点 。 您可以在浏览器中尝试它 ,或下载它使用的小型可重复使用的JavaScript实现。 .NET的实现是在AvsAn上打包AvsAn 。 这些实现是微不足道的,所以如果需要的话,应该很容易移植到任何其他语言。

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

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

…这只是强调,基于规则的系统将是棘手的build立!

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

一个愚蠢的方法是向Google询问两种可能性(使用searchAPI之一)并使用最stream行的:

要么:

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

如果你能find单词拼写的来源,如:

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

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

编辑添加:

! – 我想你可以用这个来产生你的例外: http : //www.speech.cs.cmu.edu/cgi-bin/cmudict

当然,并不是所有的东西都在字典中,这意味着并不是每个可能的exception都会在你的exception集中结束 – 但是在这种情况下,你可以默认为一个元音/一个辅音,或者使用其他一些启发式的更好的赔率。

(通过CMU字典,我很高兴看到它包括国家和一些其他地方的专有名词 – 所以它会像“乌克兰”,“今日美国报”,“乌拉尔风格的绘画”)的例子。

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

你必须手工实施,并添加例外,如果第一个字母是“H”,然后是一个“O”,如诚实,小时…,还有像欧洲,大学这样的相反的…

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

  1. 如果单词的第一个字母是辅音 – >“a”
  2. 如果单词的第一个字母是元音 – >“一”
  3. 保留一个例外列表(心脏,X光,房子) rjumnro说 。

你需要看看不定冠词的语法规则(英语语法中只有两个不定冠词 – “a”和“an”),你可能不同意这些说法是正确的,但是英语语法规则是非常明确的 :

“a和an这两个词是不定冠词,我们在以一个元音(a,e,i,o,u)开头的单词之前使用不定冠词a,在以辅音(all其他字母)“。

请注意,这意味着元音,而不是元音字母 。 例如,以“h”开头的单词,例如“荣誉”或“inheritance人”被视为元音,所以以“an”开头 – 例如“很荣幸见到你”。 以辅音开头的单词前面加上了 – 这就是为什么你说“二手车”而不是“二手车” – 因为“used”有一个“yoose”声音而不是“uhh”声音。

所以,作为一名程序员,这些是遵循的规则。 你只需要找出一个方法来确定一个单词开始的声音,而不是什么字母。 我见过这样的例子,比如Jaime 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'; } 

创build规则可能是最容易的,然后创build一个exception列表并使用它。 我不认为会有这么多。

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

我用php和javascript(!)写了一个(糟糕的)程序来阅读整个瑞典语的维基百科(或者至less从math的angular度可以达到的所有的aricles,这是我的蜘蛛的开始)。

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

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

当你在这里时,logging所有与英语不一致的事件,看看是否有错误。 去修理他们,回馈给社区。

人,我意识到这可能是一个稳定的论点,但我认为这可以比使用维基百科特设的语法规则更容易解决,最好是从中获得本地语法。

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

卡内基梅隆大学有一个伟大的在线工具,用于这种检查 – http://www.speech.cs.cmu.edu/cgi-bin/cmudict – 在125K字与匹配的39个音素。 插入一个字提供了整个音素集,其中只有第一个是重要的。

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

请注意,美国方言和英国方言有区别,正如“ A对战”中的“语法女孩”所指出的那样。

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

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

我从Python中移植了一个函数(最初来自CPAN包Lingua-EN-Inflect),它正确地确定了C#中元音的声音,并将其作为问题的答案发布。以编程方式确定是否用一个或一个? 。 你可以在这里看到代码片断。

你可以得到一个英文字典,存储在我们的正常字母写的字, 国际字母表 ?

然后用这个词来判断这个单词的开始声音,因此“a”还是“an”是合适的?

不知道这是否会比维基百科的统计方法更容易(或者更有趣)。

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

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

在语言学的图书馆里进行了一个快速的search,讨论如何处理英语的单数前缀,但是如果你挖掘得够深的话,你也许可以find一些东西。 如果不是的话 – 你可以随时编写你自己的变形库,并获得世界的声誉:-)。

我不认为你可以只填一些像“a / an”这样的锅炉板材。 否则,最终会出现假设错误,比如所有带有'h'的单词都是由'o'取代'a',而不是像'home'一样。 基本上,你最终将包括英语的逻辑或偶然发现罕见的情况下,会让你看起来很愚蠢。

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

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

也算“eu”作为辅音等。

这并不难。

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

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

怎么样? 那怎么样? 获得附加文章的名词。 以特定的forms请求它。

用文章询问名词。 许多MUD代码库存储的信息包括:

  • 一个或多个关键字
  • 一个简短的表格
  • 一个长的forms

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

你正在写一个“一对一”的Web服务吗? 退后一步,看看你是否可以在上游进一步攻击这个泄漏。 你可以build造一个大坝,但是除非你阻止它stream动,否则它将最终蔓延。

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

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

更糟糕的是,一些“诚实”的词语是从元音或辅音开始的,取决于谁在说。 更糟糕的是,一些说话者会根据他们周围的话来改变一些单词。

问题只有在你想投入多less时间和精力的情况下才能解决。 你可以在几分钟内用'aeiou'作为元音写一些东西,或者花几个月时间对目标读者进行语言分析。 在他们之间有大量的启发式方法,对一些发言者来说是正确的,对另一些发言者是错误的,但是因为不同的发言者对同一个词有不同的判断,所以不pipe你怎么做,都不可能是正确的它。

理想的方法是find可以给你答案的在线位置,dynamic查询它们并caching答案。 初学者可以用几百字来填充系统。

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

所以,没有下载所有的互联网,一个合理的解决scheme是可能的。 以下是我所做的:

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

每当下一个单词不是元音时,就使用“a”? 每当有元音时,你就用“an”

就这样说,难道你不能像“a \ s [a,e,i,o,u]。”这样的正则expression式吗? 然后把它换成“一个?

Interesting Posts