Pspell
Školení, která pořádám
Pspell asi nepatří k nejpoužívanějším rozšířením PHP, já jsem ho ale už dvakrát použil k poměrně zajímavým úkolům. Pspell je rozšíření, které v PHP umožňuje používat kontrolu pravopisu, při instalaci odpovídajícího slovníku i pro češtinu.
Skoro mě až překvapilo, jak jednoduše jde v PHP napsat aplikace pro asistované přidání háčků a čárek do textu bez diakritiky. Pro vytvoření celé aplikace se hodí i dobrá znalost JavaScriptu a pokud možno také statistických metod, z pohledu PHP je ale asi nejzajímavější funkce, která vrátí všechny možné varianty slova bez diakritiky:
<?php
define("ISO_8859_2", "áčďéěíňóřšťúůýžÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ");
define("US_ASCII", "acdeeinorstuuyzACDEEINORSTUUYZ");
/** Vrácení variant slov s diakritikou nalezených ve slovníku
* @param string začešťované slovo obvykle bez diakritiky (stávající diakritika se ponechá)
* @return array správné varianty slova - array("var1", ...)
*/
function zacesti_slovo($slovo) {
static $pspell;
if (!isset($pspell)) {
pspell_config_create("cs");
$pspell = pspell_new("cs");
}
static $pismena; // array("a" => "á", "e" => "éě", ...)
if (!isset($pismena)) {
for ($i=0; $i < strlen(US_ASCII); $i++) {
$pismena[substr(US_ASCII, $i, 1)] .= substr(ISO_8859_2, $i, 1);
}
}
$moznosti = array("");
for ($i=0; $i < strlen($slovo); $i++) {
foreach ($moznosti as $key => $val) {
$moznosti[$key] .= $slovo[$i];
for ($j=0; $j < strlen($pismena[$slovo[$i]]); $j++) {
$moznosti[] = $val . $pismena[$slovo[$i]][$j];
}
}
}
foreach ($moznosti as $key => $val) {
if (!pspell_check($pspell, $val)) {
unset($moznosti[$key]);
}
}
return $moznosti;
}
?>
Elegantní mi přijde obzvláště část, která naplní pole $moznosti
všemi možnými variantami slova. Je to sice poměrně hutné čtivo, ale svůj účel splní myslím šikovně. Připomínám, že konstrukce $slovo[$i]
se používá pro získání $i
-tého znaku řetězce $slovo
a odpovídá tedy zápisu substr($slovo, $i, 1)
.
V druhém případě jsem rozšíření Pspell použil pro kontrolu pravopisu na stránkách, tam ale kromě rozřezání textu na slova a použití správného jazyka v závislosti na hodnotách atributů lang nic až tak zajímavého není.
Diskuse
Wow, zajimava vec :) Ale chtel bych poprosit o jednu vec. Nemam rad postupy copy/paste, snazim se pouzivanej kod nejdriv pochopit -- a to tvoje husty cteni je opravdu husty, slo by k tomu priste napsat nejakej komentar ve stylu:
<?php
// V tomto cyklu vytvarime maly zombiky, zasadime je do pole.
// V tom poli je pak budeme zalevat, stanou se z nich vetsi zombici,
// az z nich bude cela armada, ukoncime produkci, jsme tak pripraveni k boji.
for ($i=0; $i < strlen($slovo); $i++) {
foreach ($moznosti as $key => $val) {
$moznosti[$key] .= $slovo{$i};
for ($j=0; $j < strlen($pismena[$slovo{$i}]); $j++) {
$moznosti[] = $val . $pismena[$slovo{$i}]{$j};
}
}
}
?>
Rozumim, ze komentar by mohl delsi nez samotnej kod (a ze "A TRUE Klingon warrior does not comment his code!"), ale prece jen by to hodne pomohlo k rychlymu ziskani prehledu o tom, co ten kod vlastne dela. Dik :)
Leo:
A k tomu bych se pridat, komentaru pro nas natvrdlejsi neni nikdy dost, diky predem, Leo
Pokusím se, ať to k něčemu je. Ono se PHP dá číst líp než třeba svahilština, ale pro spoustu lidí pořád hůř než čeština :-).
Ten kód postupuje po jednotlivých písmenech proměnné $slovo, ke všem existujícím prvkům v poli $moznosti přidá aktuální písmeno (bez diakritiky) a následně do pole přidá možnosti vzniklé doplněním diakritiky. Takže z řetězce "ale" vznikne postupně:
array("a", "á")
array("al", "ál")
array("ale", "ále", "alé", "alě", "álé", "álě")
.. a pokud jsem to pochopoval spravne, tak se potom kazdej ten prvek vzniklyho pole prozene pspell_check()-em, jestli takovy slovo existuje v danym jazyce -- takze treba slova jako "álě" se unset()nou. Hmm, chytry vyuziti spellcheckeru ;)
___
ne, ze by PHP bylo pro me svahilstinou, ale mozna i ty sam za pul roku bys svuj komentar ocenil ;) (bez urazky, samo)
peta:
Souhlasím s tebou, kód příkladu jsem si prošel a postupně jsem si ho přepsal do srozumitelnější podoby. Sice je o nějakých deset řádků delší, možná je i o pár setinek pomalejší, ale alespoň bude dobře čitelný i po delší době...
Orrorin:
až na tu exponenciální složitost dobrý
Dobrá poznámka. Složitost je exponenciální vzhledem k délce slova, která je omezená, takže je to i tak schopné provozu. Složitost by se dala významně srazit, pokud bychom měli přímý přístup ke všem slovům s diakritikou. Pokud máme k dispozici pouze funkci pspell_check(), tak to vylepšit podle mě nepůjde.
Diskuse je zrušena z důvodu spamu.