PHPのSchinke Latin Stemmingアルゴリズム
質問
このウェブサイト ダウンロードするための「Schinke Latin Stemmingアルゴリズム」を提供して、 スノーボール 幹システム。
このアルゴリズムを使用したいのですが、スノーボールを使用したくありません。
良いこと:あります いくつかの擬似コード そのページでは、PHP関数に変換できます。これが私が試したことです:
<?php
function stemLatin($word) {
// output = array(NOUN-BASED STEM, VERB-BASED STEM)
// DEFINE CLASSES BEGIN
$queWords = array('atque', 'quoque', 'neque', 'itaque', 'absque', 'apsque', 'abusque', 'adaeque', 'adusque', 'denique', 'deque', 'susque', 'oblique', 'peraeque', 'plenisque', 'quandoque', 'quisque', 'quaeque', 'cuiusque', 'cuique', 'quemque', 'quamque', 'quaque', 'quique', 'quorumque', 'quarumque', 'quibusque', 'quosque', 'quasque', 'quotusquisque', 'quousque', 'ubique', 'undique', 'usque', 'uterque', 'utique', 'utroque', 'utribique', 'torque', 'coque', 'concoque', 'contorque', 'detorque', 'decoque', 'excoque', 'extorque', 'obtorque', 'optorque', 'retorque', 'recoque', 'attorque', 'incoque', 'intorque', 'praetorque');
$suffixesA = array('ibus, 'ius, 'ae, 'am, 'as, 'em', 'es', ia', 'is', 'nt', 'os', 'ud', 'um', 'us', 'a', 'e', 'i', 'o', 'u');
$suffixesB = array('iuntur', 'beris', 'erunt', 'untur', 'iunt', 'mini', 'ntur', 'stis', 'bor', 'ero', 'mur', 'mus', 'ris', 'sti', 'tis', 'tur', 'unt', 'bo', 'ns', 'nt', 'ri', 'm', 'r', 's', 't');
// DEFINE CLASSES END
$word = strtolower(trim($word)); // make string lowercase + remove white spaces before and behind
$word = str_replace('j', 'i', $word); // replace all <j> by <i>
$word = str_replace('v', 'u', $word); // replace all <v> by <u>
if (substr($word, -3) == 'que') { // if word ends with -que
if (in_array($word, $queWords)) { // if word is a queWord
return array($word, $word); // output queWord as both noun-based and verb-based stem
}
else {
$word = substr($word, 0, -3); // remove the -que
}
}
foreach ($suffixesA as $suffixA) { // remove suffixes for noun-based forms (list A)
if (substr($word, -strlen($suffixA)) == $suffixA) { // if the word ends with that suffix
$word = substr($word, 0, -strlen($suffixA)); // remove the suffix
break; // remove only one suffix
}
}
if (strlen($word) >= 2) { $nounBased = $word; } else { $nounBased = ''; } // add only if word contains two or more characters
foreach ($suffixesB as $suffixB) { // remove suffixes for verb-based forms (list B)
if (substr($word, -strlen($suffixA)) == $suffixA) { // if the word ends with that suffix
switch ($suffixB) {
case 'iuntur', 'erunt', 'untur', 'iunt', 'unt': $word = substr($word, 0, -strlen($suffixB)).'i'; break; // replace suffix by <i>
case 'beris', 'bor', 'bo': $word = substr($word, 0, -strlen($suffixB)).'bi'; break; // replace suffix by <bi>
case 'ero': $word = substr($word, 0, -strlen($suffixB)).'eri'; break; // replace suffix by <eri>
default: $word = substr($word, 0, -strlen($suffixB)); break; // remove the suffix
}
break; // remove only one suffix
}
}
if (strlen($word) >= 2) { $verbBased = $word; } else { $verbBased = ''; } // add only if word contains two or more characters
return array($nounBased, $verbBased);
}
?>
私の質問:
1)このコードは正しく機能しますか?アルゴリズムのルールに従いますか?
2)コード(パフォーマンス)をどのように改善できますか?
事前にどうもありがとうございました!
解決
いいえ、機能は機能しません。構文エラーが含まれています。たとえば、あなたは閉鎖されていない引用を持っています、そしてあなたは間違ったものを使用します switch
構文。
これが私の機能の書き直しです。そのページの擬似アルゴリズムはそれほど正確ではないので、私はいくつかの解釈をしなければなりませんでした。この記事で言及されている例が機能しているように解釈しました。
また、いくつかの最適化を行いました。最初のものは、単語と接尾辞配列を定義することです static
. 。したがって、この関数へのすべての呼び出しは、良い前面のパフォーマンスであると同じ配列を共有しています;)
さらに、配列をより効果的に使用できるように調整しました。私は変更しました $queWords
アレイは、速度ではなく、高速ハッシュテーブルルックアップに使用できるように配列 in_array
. 。さらに、配列内の接尾辞の長さを保存しました。したがって、実行時にそれらを計算する必要はありません(これは本当に、本当に遅いです)。私はよりマイナーな最適化を行ったかもしれません。
このコードがどれほど速いかはわかりませんが、はるかに速いはずです。さらに、提供された例で機能します。
これがコードです:
<?php
function stemLatin($word) {
static $queWords = array(
'atque' => 1,
'quoque' => 1,
'neque' => 1,
'itaque' => 1,
'absque' => 1,
'apsque' => 1,
'abusque' => 1,
'adaeque' => 1,
'adusque' => 1,
'denique' => 1,
'deque' => 1,
'susque' => 1,
'oblique' => 1,
'peraeque' => 1,
'plenisque' => 1,
'quandoque' => 1,
'quisque' => 1,
'quaeque' => 1,
'cuiusque' => 1,
'cuique' => 1,
'quemque' => 1,
'quamque' => 1,
'quaque' => 1,
'quique' => 1,
'quorumque' => 1,
'quarumque' => 1,
'quibusque' => 1,
'quosque' => 1,
'quasque' => 1,
'quotusquisque' => 1,
'quousque' => 1,
'ubique' => 1,
'undique' => 1,
'usque' => 1,
'uterque' => 1,
'utique' => 1,
'utroque' => 1,
'utribique' => 1,
'torque' => 1,
'coque' => 1,
'concoque' => 1,
'contorque' => 1,
'detorque' => 1,
'decoque' => 1,
'excoque' => 1,
'extorque' => 1,
'obtorque' => 1,
'optorque' => 1,
'retorque' => 1,
'recoque' => 1,
'attorque' => 1,
'incoque' => 1,
'intorque' => 1,
'praetorque' => 1,
);
static $suffixesNoun = array(
'ibus' => 4,
'ius' => 3,
'ae' => 2,
'am' => 2,
'as' => 2,
'em' => 2,
'es' => 2,
'ia' => 2,
'is' => 2,
'nt' => 2,
'os' => 2,
'ud' => 2,
'um' => 2,
'us' => 2,
'a' => 1,
'e' => 1,
'i' => 1,
'o' => 1,
'u' => 1,
);
static $suffixesVerb = array(
'iuntur' => 6,
'beris' => 5,
'erunt' => 5,
'untur' => 5,
'iunt' => 4,
'mini' => 4,
'ntur' => 4,
'stis' => 4,
'bor' => 3,
'ero' => 3,
'mur' => 3,
'mus' => 3,
'ris' => 3,
'sti' => 3,
'tis' => 3,
'tur' => 3,
'unt' => 3,
'bo' => 2,
'ns' => 2,
'nt' => 2,
'ri' => 2,
'm' => 1,
'r' => 1,
's' => 1,
't' => 1,
);
$stems = array($word, $word);
$word = strtr(strtolower(trim($word)), 'jv', 'iu'); // trim, lowercase and j => i, v => u
if (substr($word, -3) == 'que') {
if (isset($queWords[$word])) {
return array($word, $word);
}
$word = substr($word, 0, -3);
}
foreach ($suffixesNoun as $suffix => $length) {
if (substr($word, -$length) == $suffix) {
$tmp = substr($word, 0, -$length);
if (isset($tmp[1]))
$stems[0] = $tmp;
break;
}
}
foreach ($suffixesVerb as $suffix => $length) {
if (substr($word, -$length) == $suffix) {
switch ($suffix) {
case 'iuntur':
case 'erunt':
case 'untur':
case 'iunt':
case 'unt':
$tmp = substr_replace($word, 'i', -$length, $length);
break;
case 'beris':
case 'bor':
case 'bo':
$tmp = substr_replace($word, 'bi', -$length, $length);
break;
case 'ero':
$tmp = substr_replace($word, 'eri', -$length, $length);
break;
default:
$tmp = substr($word, 0, -$length);
}
if (isset($tmp[1]))
$stems[1] = $tmp;
break;
}
}
return $stems;
}
var_dump(stemLatin('aquila'));
var_dump(stemLatin('portat'));
var_dump(stemLatin('portis'));
他のヒント
私が知る限り、これはあなたのリンクで説明されているアルゴリズムに従い、正しく動作するはずです。 (の定義にある構文エラーとは別に $suffixesA
- アポストロフィのいくつかが欠けています。)
パフォーマンスに関しては、ここには多くのことが得られるようには見えませんが、頭に浮かぶことがいくつかあります。
これがスクリプトの1回の実行中に何度も呼び出される場合、関数の外側にこれらの配列を定義することで何かが得られる可能性があります。
これら2つを組み合わせることもできます str_replace
s 1つに: $word = str_replace(array('j','v'), array('i','u'), $word);
, 、または、単一文字を単一文字に置き換えるので、使用できます $word = strtr($word,'jv','iu');
- しかし、私はそれが実際に大きな違いをもたらすとは思わない。確実に試してみる必要があります。