私は、アプリケーションで出力して説明する必要がある名詞(ex "house"、 "exclamation point"、 "apple")のデータベースを持っています。 "a"や "an"を使用せずにアイテムを説明するのは難しいです。 "家は大です"、 "感嘆符は小です"など"a"または "an"でオブジェクトを記述するかどうかをプログラムで決定しますか?
機能はありますか?ライブラリ、またはハック私はAまたはANで任意の名詞を記述する方が適切かどうかをPHPで判断できますか?
私は、アプリケーションで出力して説明する必要がある名詞(ex "house"、 "exclamation point"、 "apple")のデータベースを持っています。 "a"や "an"を使用せずにアイテムを説明するのは難しいです。 "家は大です"、 "感嘆符は小です"など"a"または "an"でオブジェクトを記述するかどうかをプログラムで決定しますか?
機能はありますか?ライブラリ、またはハック私はAまたはANで任意の名詞を記述する方が適切かどうかをPHPで判断できますか?
適切な不定冠詞を決定することです。 Lingua::EN::Inflect
は素晴らしい仕事をするPerlモジュールです。私は関連するコードを抽出し、それを下に貼り付けました。これは単なるケースといくつかの正規表現なので、PHPに移植するのは難しいことではありません。誰かが興味があれば、友人はそれをPython hereに移植しました。
# 2. INDEFINITE ARTICLES
# 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!)
my $A_abbrev = q{
(?! 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.
my $A_y_cons = 'y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt)';
# EXCEPTIONS TO EXCEPTIONS
my $A_explicit_an = enclose join '|',
(
"euler",
"hour(?!i)", "heir", "honest", "hono",
);
my $A_ordinal_an = enclose join '|',
(
"[aefhilmnorsx]-?th",
);
my $A_ordinal_a = enclose join '|',
(
"[bcdgjkpqtuvwyz]-?th",
);
sub A {
my ($str, $count) = @_;
my ($pre, $word, $post) = ($str =~ m/\A(\s*)(?:an?\s+)?(.+?)(\s*)\Z/i);
return $str unless $word;
my $result = _indef_article($word,$count);
return $pre.$result.$post;
}
sub AN { goto &A }
sub _indef_article {
my ($word, $count) = @_;
$count = $persistent_count
if !defined($count) && defined($persistent_count);
return "$count $word"
if defined $count && $count!~/^($PL_count_one)$/io;
# HANDLE USER-DEFINED VARIANTS
my $value;
return "$value $word"
if defined($value = ud_match($word, @A_a_user_defined));
# HANDLE ORDINAL FORMS
$word =~ /^($A_ordinal_a)/i and return "a $word";
$word =~ /^($A_ordinal_an)/i and return "an $word";
# HANDLE SPECIAL CASES
$word =~ /^($A_explicit_an)/i and return "an $word";
$word =~ /^[aefhilmnorsx]$/i and return "an $word";
$word =~ /^[bcdgjkpqtuvwyz]$/i and return "a $word";
# HANDLE ABBREVIATIONS
$word =~ /^($A_abbrev)/ox and return "an $word";
$word =~ /^[aefhilmnorsx][.-]/i and return "an $word";
$word =~ /^[a-z][.-]/i and return "a $word";
# HANDLE CONSONANTS
$word =~ /^[^aeiouy]/i and return "a $word";
# HANDLE SPECIAL VOWEL-FORMS
$word =~ /^e[uw]/i and return "a $word";
$word =~ /^onc?e\b/i and return "a $word";
$word =~ /^uni([^nmd]|mo)/i and return "a $word";
$word =~ /^ut[th]/i and return "an $word";
$word =~ /^u[bcfhjkqrst][aeiou]/i and return "a $word";
# HANDLE SPECIAL CAPITALS
$word =~ /^U[NK][AIEO]?/ and return "a $word";
# HANDLE VOWELS
$word =~ /^[aeiou]/i and return "an $word";
# HANDLE y... (BEFORE CERTAIN CONSONANTS IMPLIES (UNNATURALIZED) "i.." SOUND)
$word =~ /^($A_y_cons)/io and return "an $word";
# OTHERWISE, GUESS "a"
return "a $word";
}
これは完璧に見えます、私はかなりPHPに新しいので、移植は少しの冒険になります! – MarathonStudios
これは役に立ちます!誰かがPHPに移植する時間を見つけたら、ここに投稿してください! –
私はこれを数日後に移植し、元の質問に投稿します – MarathonStudios
ゼロから書くのはかなり簡単です。tbh。単語が母音で始まる場合、それは 'a'を取得します。子音で始まる場合、それは 'an'を取得します。プログラマチックに行うのは簡単です。もしあなたが何かの悩みがあるなら(例えば、BBCの英国スタイルの "歴史的な機会"を使うかもしれません)、あなたはそれらを個別に扱うことができます。
複数形ではなく、 'a'/'an'文法規則のみで、インフレクターを使用するような種類です。 CakePHPやRailsが、どのようにして境界条件を扱うかなど、概念のより徹底的な議論をどのように扱うのか調べてみましょう。例えば、「鹿」を複数形で使用することは望ましくありません。 「gooses」なので、「宇宙」や吸引された/吸引されていない「H」のようなあなた自身の縁のように、個々に処理する必要があります。
このようなソリューションを探していたので、ありがとうございましたmarcog。ここでは、ポートへの試みがあなたの友人のPythonのバージョンです(おそらくありますので、私は、PythonやPerlを知っていないいくつかのミス):1ビット(コメント「//わからないこれが何をするか」の下に)あります
function indefinite_article($word) {
// Lowercase version of the word
$word_lower = strtolower($word);
// An 'an' word (specific start of words that should be preceeded by 'an')
$an_words = array('euler', 'heir', 'honest', 'hono');
foreach($an_words as $an_word) {
if(substr($word_lower,0,strlen($an_word)) == $an_word) return "an";
}
if(substr($word_lower,0,4) == "hour" and substr($word_lower,0,5) != "houri") return "an";
// An 'an' letter (single letter word which should be preceeded by 'an')
$an_letters = array('a','e','f','h','i','l','m','n','o','r','s','x');
if(strlen($word) == 1) {
if(in_array($word_lower,$an_letters)) return "an";
else return "a";
}
// Capital words which should likely by preceeded by 'an'
if(preg_match('/(?!FJO|[HLMNS]Y.|RY[EO]|SQU|(F[LR]?|[HL]|MN?|N|RH?|S[CHKLMNPTVW]?|X(YL)?)[AEIOU])[FHLMNRSX][A-Z]/', $word)) return "an";
// Special cases where a word that begins with a vowel should be preceeded by 'a'
$regex_array = array('^e[uw]','^onc?e\b','^uni([^nmd]|mo)','^u[bcfhjkqrst][aeiou]');
foreach($regex_array as $regex) {
if(preg_match('/'.$regex.'/',$word_lower)) return "a";
}
// Special capital words
if(preg_match('/^U[NK][AIEO]/',$word)) return "a";
// Not sure what this does
else if($word == strtoupper($word)) {
$array = array('a','e','d','h','i','l','m','n','o','r','s','x');
if(in_array($word_lower[0],$array)) return "an";
else return "a";
}
// Basic method of words that begin with a vowel being preceeded by 'an'
$vowels = array('a','e','i','o','u');
if(in_array($word_lower[0],$vowels)) return "an";
// Instances where y follwed by specific letters is preceeded by 'an'
if(preg_match('/^y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt)/', $word_lower)) return "an";
// Default to 'a'
return "a";
}
こと私はそれが何をしたのか分からなかった。誰かがそれを理解できるなら、私は知ってうれしいです。
これはC#プロジェクトに必要なので、ここでは上記のPython codeのC#ポートです。ソースファイルにusing System.Text.RegularExpressions;
を必ず含めてください。
private string GetIndefiniteArticle(string noun_phrase)
{
string word = null;
var m = Regex.Match(noun_phrase, @"\w+");
if (m.Success)
word = m.Groups[0].Value;
else
return "an";
var wordi = word.ToLower();
foreach (string anword in new string[] { "euler", "heir", "honest", "hono" })
if (wordi.StartsWith(anword))
return "an";
if (wordi.StartsWith("hour") && !wordi.StartsWith("houri"))
return "an";
var char_list = new char[] { 'a', 'e', 'd', 'h', 'i', 'l', 'm', 'n', 'o', 'r', 's', 'x' };
if (wordi.Length == 1)
{
if (wordi.IndexOfAny(char_list) == 0)
return "an";
else
return "a";
}
if (Regex.Match(word, "(?!FJO|[HLMNS]Y.|RY[EO]|SQU|(F[LR]?|[HL]|MN?|N|RH?|S[CHKLMNPTVW]?|X(YL)?)[AEIOU])[FHLMNRSX][A-Z]").Success)
return "an";
foreach (string regex in new string[] { "^e[uw]", "^onc?e\b", "^uni([^nmd]|mo)", "^u[bcfhjkqrst][aeiou]" })
{
if (Regex.IsMatch(wordi, regex))
return "a";
}
if (Regex.IsMatch(word, "^U[NK][AIEO]"))
return "a";
else if (word == word.ToUpper())
{
if (wordi.IndexOfAny(char_list) == 0)
return "an";
else
return "a";
}
if (wordi.IndexOfAny(new char[] { 'a', 'e', 'i', 'o', 'u' }) == 0)
return "an";
if (Regex.IsMatch(wordi, "^y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt)"))
return "an";
return "a";
}
C#の実装を探しているなら、私はウィキペディアから抽出された実際の使用パターンを使用して、奇妙なコーナーケースでも処理するhttp://code.google.com/p/a-vs-an/を書きました。ナゲットのAvsAnです。 –
私はこのような解決方法も探していましたが、JavaScriptで探していました。だから私はJSにそれを移植され、あなたがチェックアウトすることができますここではgithubの中の実際のプロジェクトhttps://github.com/rigoneri/indefinite-article.js
は、コードスニペットです:
function indefinite_article(phrase) {
// Getting the first word
var match = /\w+/.exec(phrase);
if (match)
var word = match[0];
else
return "an";
var l_word = word.toLowerCase();
// Specific start of words that should be preceeded by 'an'
var alt_cases = ["honest", "hour", "hono"];
for (var i in alt_cases) {
if (l_word.indexOf(alt_cases[i]) == 0)
return "an";
}
// Single letter word which should be preceeded by 'an'
if (l_word.length == 1) {
if ("aedhilmnorsx".indexOf(l_word) >= 0)
return "an";
else
return "a";
}
// Capital words which should likely be preceeded by 'an'
if (word.match(/(?!FJO|[HLMNS]Y.|RY[EO]|SQU|(F[LR]?|[HL]|MN?|N|RH?|S[CHKLMNPTVW]?|X(YL)?)[AEIOU])[FHLMNRSX][A-Z]/)) {
return "an";
}
// Special cases where a word that begins with a vowel should be preceeded by 'a'
regexes = [/^e[uw]/, /^onc?e\b/, /^uni([^nmd]|mo)/, /^u[bcfhjkqrst][aeiou]/]
for (var i in regexes) {
if (l_word.match(regexes[i]))
return "a"
}
// Special capital words (UK, UN)
if (word.match(/^U[NK][AIEO]/)) {
return "a";
}
else if (word == word.toUpperCase()) {
if ("aedhilmnorsx".indexOf(l_word[0]) >= 0)
return "an";
else
return "a";
}
// Basic method of words that begin with a vowel being preceeded by 'an'
if ("aeiou".indexOf(l_word[0]) >= 0)
return "an";
// Instances where y follwed by specific letters is preceeded by 'an'
if (l_word.match(/^y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt)/))
return "an";
return "a";
}
私は 'd'が "aedhilmnorsx"で削除されるべきだと思います。 – spencercooly
ルールベースのシステムの問題は、彼らがエッジケースと悪い扱うということですそして、それらは複雑であること。意思決定を実際のデータに基づいて行うことができれば、より良い結果が得られます。 this answerでは、ウィキペディアを使ってルックアップ辞書を構築し、そのような辞書を使って(非常に単純な)JavaScript実装にリンクする方法について説明します。
接頭辞辞書は頭字語と数字をかなりよく扱いますが、多少の努力をすればおそらくもっとうまくいくでしょう。
私は、このstackoverflow投稿https://stackoverflow.com/a/1288473/1526020で説明されているように、人気のあるJS a-vs-an codeのPHPポートを作成しました。
ギブスページ:https://github.com/UseAllFive/a-vs-an。
など。
$result = $aVsAn->query('0800 number');
print_r($result);
戻り
Array
(
[aCount] => 8
[anCount] => 25
[prefix] => 08
[article] => an
)
私は実際にPHPが肥大化していることを考え始めるかもしれないこれをしたPHPのコア機能があった場合。 – webbiedave
文法的に、hで始まる単語(houseなど)は、aまたはan ...のいずれかになります。 (hは黙っている)正直な人、houndの犬(hは難しい)/ホテル、(ちょっと恥知らずな話し手による) –
@webbiedave - これをしたphp core関数があれば、私は、PHPのコア開発者が英語以外の言語の存在を忘れてしまったと思っています。そして、次のトリックのために、フランス名詞の前にle、la、lesまたはl 'を付けるべきかどうかを特定する関数 –