可能重复:
以编程方式确定是用“a”还是“an”来描述对象?
我需要输出这样的句子:
Are you An American?
或者:
Are you A German?
我有国家名称,但我需要为该国家名称找到正确的文章 A 或 An。
是否有任何 php 库/实用程序函数可以实现该语法规则,除了此处所述的所有例外情况?我想到了 Zend_Locale,但没有找到足够的东西。
我也用谷歌搜索过,但是“A vs An PHP”的结果并没有真正的帮助。
可能重复:
以编程方式确定是用“a”还是“an”来描述对象?
我需要输出这样的句子:
Are you An American?
或者:
Are you A German?
我有国家名称,但我需要为该国家名称找到正确的文章 A 或 An。
是否有任何 php 库/实用程序函数可以实现该语法规则,除了此处所述的所有例外情况?我想到了 Zend_Locale,但没有找到足够的东西。
我也用谷歌搜索过,但是“A vs An PHP”的结果并没有真正的帮助。
请参阅此答案以获取一些有用的解决方案。答案包含 Perl 模块的摘录Lingua::EN::Inflect
,似乎在确定使用哪个不定冠词方面做得很好:
A("cat") # -> "a cat"
AN("cat") # -> "a cat"
A("euphemism") # -> "a euphemism"
A("Euler number") # -> "an Euler number"
A("hour") # -> "an hour"
A("houri") # -> "a houri"
规则被定义为正则表达式,因此移植到 PHP 应该不会太难。
编辑:我最终将其转换为 PHP(也可在github上找到)。
用法:print IndefiniteArticle::A("umbrella"); // an umbrella
<?php
class IndefiniteArticle
{
public static function AN($input, $count=1) {
return self::A($input, $count);
}
public static function A($input, $count=1) {
$matches = array();
$matchCount = preg_match("/\A(\s*)(?:an?\s+)?(.+?)(\s*)\Z/i", $input, $matches);
list($all, $pre, $word, $post) = $matches;
if(!$word)
return $input;
$result = self::_indef_article($word, $count);
return $pre.$result.$post;
}
# THIS PATTERN MATCHES STRINGS OF CAPITALS STARTING WITH A "VOWEL-SOUND"
# CONSONANT FOLLOWED BY ANOTHER CONSONANT, AND WHICH ARE NOT LIKELY
# TO BE REAL WORDS (OH, ALL RIGHT THEN, IT'S JUST MAGIC!)
private static $A_abbrev = "(?! FJO | [HLMNS]Y. | RY[EO] | SQU
| ( F[LR]? | [HL] | MN? | N | RH? | S[CHKLMNPTVW]? | X(YL)?) [AEIOU])
[FHLMNRSX][A-Z]
";
# THIS PATTERN CODES THE BEGINNINGS OF ALL ENGLISH WORDS BEGINING WITH A
# 'y' FOLLOWED BY A CONSONANT. ANY OTHER Y-CONSONANT PREFIX THEREFORE
# IMPLIES AN ABBREVIATION.
private static $A_y_cons = 'y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt)';
# EXCEPTIONS TO EXCEPTIONS
private static $A_explicit_an = "euler|hour(?!i)|heir|honest|hono";
private static $A_ordinal_an = "[aefhilmnorsx]-?th";
private static $A_ordinal_a = "[bcdgjkpqtuvwyz]-?th";
private static function _indef_article($word, $count) {
if($count != 1) // TODO: Check against $PL_count_one instead
return "$count $word";
# HANDLE USER-DEFINED VARIANTS
// TODO
# HANDLE ORDINAL FORMS
if(preg_match("/^(".self::$A_ordinal_a.")/i", $word)) return "a $word";
if(preg_match("/^(".self::$A_ordinal_an.")/i", $word)) return "an $word";
# HANDLE SPECIAL CASES
if(preg_match("/^(".self::$A_explicit_an.")/i", $word)) return "an $word";
if(preg_match("/^[aefhilmnorsx]$/i", $word)) return "an $word";
if(preg_match("/^[bcdgjkpqtuvwyz]$/i", $word)) return "a $word";
# HANDLE ABBREVIATIONS
if(preg_match("/^(".self::$A_abbrev.")/x", $word)) return "an $word";
if(preg_match("/^[aefhilmnorsx][.-]/i", $word)) return "an $word";
if(preg_match("/^[a-z][.-]/i", $word)) return "a $word";
# HANDLE CONSONANTS
if(preg_match("/^[^aeiouy]/i", $word)) return "a $word";
# HANDLE SPECIAL VOWEL-FORMS
if(preg_match("/^e[uw]/i", $word)) return "a $word";
if(preg_match("/^onc?e\b/i", $word)) return "a $word";
if(preg_match("/^uni([^nmd]|mo)/i", $word)) return "a $word";
if(preg_match("/^ut[th]/i", $word)) return "an $word";
if(preg_match("/^u[bcfhjkqrst][aeiou]/i", $word)) return "a $word";
# HANDLE SPECIAL CAPITALS
if(preg_match("/^U[NK][AIEO]?/", $word)) return "a $word";
# HANDLE VOWELS
if(preg_match("/^[aeiou]/i", $word)) return "an $word";
# HANDLE y... (BEFORE CERTAIN CONSONANTS IMPLIES (UNNATURALIZED) "i.." SOUND)
if(preg_match("/^(".self::$A_y_cons.")/i", $word)) return "an $word";
# OTHERWISE, GUESS "a"
return "a $word";
}
}
自己动手很简单:
function an($str) {
$vowels = "aeiou";
if (strpos($vowels, strtolower(substr($str, 0, 1))) !== false) {
return "An " . $str;
}
else {
return "A " . $str;
}
}
本质上,如果它以元音开头,则使用“An”,否则使用“A”。
可能有一些边缘情况不是这样,但我想不出任何想法。如果你找到了一个,在你做一般测试之前明确地测试它:
function an($str) {
if ($str == "foobarbaz") {
return "An";
}
$vowels = "aeiou";
if (strpos($vowels, strtolower(substr($str, 0, 1))) !== false) {
return "An " . $str;
}
else {
return "A " . $str;
}
}
试试这个:-
$vowel_arr=array('a','e','i','o','u');
$string="America";
$len=strtolower(substr($string,0,1));
if(in_array($len,$vowel_arr))
$pre = "an";
else
$pre = "a";
echo $pre." ".$string;
我建议创建一个非常简单的函数。
此函数将国家名称作为参数并查看第一个字符。如果字符来自这个数组
$an_char_array = array('a', 'e', 'i', 'o');
那么你会return "an {$country}";
否则return "a {$country}";
。
您应该首先考虑任何异常并处理它们,然后执行一般部分。
函数可能如下所示:
function prependAricle($word) {
// handle exceptions here, e.g.:
$an_exceptions = array('umbrella'/*, ...*/);
$a_exceptions = array('pity'/*, ...*/);
if(in_array(strtolower($word), $an_exceptions))
return "an {$word}";
if(in_array(strtolower($word), $a_exceptions))
return "a {$word}";
// handle general rule
$an_char_array = array('a', 'e', 'i', 'o', 'A', 'E', 'I', 'O');
if(in_array(substr($word, 0, 1), $an_char_array))
return "an {$word}";
else
return "a {$word}";
}