خوارزمية Schinke اللاتينية في PHP
سؤال
هذا الموقع يقدم "خوارزمية Schinke Latin Crateming" للتنزيل لاستخدامها في كرة الثلج نظام التنقي.
أريد استخدام هذه الخوارزمية ، لكنني لا أريد استخدام كرة الثلج.
الشيء الجيد: هناك بعض الكود الكاذب في تلك الصفحة التي يمكنك ترجمتها إلى وظيفة 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
- أنت تفتقد زوجين من الفواصل.)
من ناحية الأداء ، لا يبدو أن هناك الكثير مما يكسبه هنا ، ولكن هناك بعض الأشياء التي تتبادر إلى الذهن.
إذا تم استدعاء هذا عدة مرات أثناء تنفيذ واحد للنص ، فقد يكون هناك شيء اكتسبه من خلال تحديد هذه المصفوفات خارج الوظيفة - لا أعتقد أن PHP ذكي بما يكفي لتخزين هذه المصفوفات بين المكالمات إلى الوظيفة.
يمكنك أيضًا الجمع بين هذين الاثنين str_replace
في واحد: $word = str_replace(array('j','v'), array('i','u'), $word);
, ، أو نظرًا لأنك تستبدل أحرفًا واحدة بأحرف واحدة ، يمكنك استخدامها $word = strtr($word,'jv','iu');
- لكنني لا أعتقد أن هذا سيحدث فرقًا كبيرًا في الممارسة العملية. سيكون عليك تجربتها لتكون متأكدا.