Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Эвристическое (без словаря) извлечение корня из русского слова.

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Стеммер Портера
snikers987
Отправлено: 13 Ноября, 2011 - 15:07:44
Post Id



Участник


Покинул форум
Сообщений всего: 1239
Дата рег-ции: Сент. 2011  
Откуда: Крым


Помог: 25 раз(а)




Искал поиском по форуму и не нашел данной темы, тема в общем-то принципиально не новая, но думаю для тех кто о ней не знают (новички имеются ввиду, ибо на них форум в основном в данное время и направлен) найдут ее весьма интересной

http://snowball[dot]tartarus[dot]org/alg[dot][dot][dot]ian/stemmer[dot]html

Class:

Спойлер (Отобразить)


Пример использования:

PHP:
скопировать код в буфер обмена
  1. $stemmer = new Lingua_Stem_Ru();
  2. echo $stemmer->stem_word('Котеровыми');


От себя внес изменения и теперь все корректно работает с UTF-8.
(Добавление)
немного переработал class
PHP:
скопировать код в буфер обмена
  1.  
  2. class Lingua_Stem_Ru
  3. {
  4.     private $VERSION = "0.02";
  5.         private $unset_predlog = true; //удалять пердлоги ?
  6.     private $Stem_Caching = 0;
  7.     private $Stem_Cache = array();
  8.     private $VOWEL = '/аеиоуыэюя/u';
  9.     private $PERFECTIVEGROUND = '/((ив|ивши|ившись|ыв|ывши|ывшись)|((?<=[ая])(в|вши|вшись)))$/u';
  10.     private $REFLEXIVE = '/(с[яь])$/u';
  11.     private $ADJECTIVE = '/(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|еых|ую|юю|ая|яя|ою|ею)$/u';
  12.     private $PARTICIPLE = '/((ивш|ывш|ующ)|((?<=[ая])(ем|нн|вш|ющ|щ)))$/u';
  13.     private $VERB = '/((ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ены|ить|ыть|ишь|ую|ю)|((?<=[ая])(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)))$/u';
  14.     private $NOUN = '/(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|и|ы|ь|ию|ью|ю|ия|ья|я)$/u';
  15.     private $RVRE = '/^(.*?[аеиоуыэюя])(.*)$/u';
  16.     private $DERIVATIONAL = '/[^аеиоуыэюя][аеиоуыэюя]+[^аеиоуыэюя]+[аеиоуыэюя].*(?<=о)сть?$/u';
  17.         private $PREDLOG = '/(^|\s)(и|для|в|на|под|из|с|по)(\s|$)/u';
  18.         private function s(&$s, $re, $to)
  19.     {
  20.         $orig = $s;
  21.         $s = preg_replace($re, $to, $s);
  22.         return $orig !== $s;
  23.     }
  24.  
  25.    private function m($s, $re)
  26.     {
  27.         return preg_match($re, $s);
  28.     }
  29.         public function stem_string($words) // string stem_string( string $words )
  30.     {
  31.         $word=explode(' ',$words);
  32.         for ($i=0;$i<count($word);$i++)
  33.         {
  34.                 if ($this->unset_predlog === TRUE) $word[$i] = preg_replace($this->PREDLOG, '', $word[$i]);
  35.                         $word[$i]=$this->stem_word($word[$i]);
  36.                         if(empty($word[$i])) unset($word[$i]);
  37.         }
  38.         return implode(' ',$word); //if you need return array change on -> return $word;
  39.     }
  40.        
  41.    private function stem_word($word)
  42.     {
  43.                 mb_regex_encoding( 'UTF-8' );
  44.                 mb_internal_encoding( 'UTF-8' );
  45.         $word = mb_strtolower($word);
  46.         $word= str_ireplace('ё', 'е', $word);
  47.         # Check against cache of stemmed words
  48.        if ($this->Stem_Caching && isset($this->Stem_Cache[$word])) {
  49.             return $this->Stem_Cache[$word];
  50.         }
  51.        
  52.                 $stem = $word;
  53.         do {
  54.           if (!preg_match($this->RVRE, $word, $p)) break;
  55.           $start = $p[1];
  56.           $RV = $p[2];
  57.           if (!$RV) break;
  58.  
  59.           # Step 1
  60.          if (!$this->s($RV, $this->PERFECTIVEGROUND, '')) {
  61.               $this->s($RV, $this->REFLEXIVE, '');
  62.  
  63.               if ($this->s($RV, $this->ADJECTIVE, '')) {
  64.                   $this->s($RV, $this->PARTICIPLE, '');
  65.               } else {
  66.                   if (!$this->s($RV, $this->VERB, ''))
  67.                       $this->s($RV, $this->NOUN, '');
  68.               }
  69.           }
  70.  
  71.           # Step 2
  72.          $this->s($RV, '/и$/', '');
  73.  
  74.           # Step 3
  75.          if ($this->m($RV, $this->DERIVATIONAL))
  76.               $this->s($RV, '/ость?$/', '');
  77.  
  78.           # Step 4
  79.          if (!$this->s($RV, '/ь$/', '')) {
  80.               $this->s($RV, '/ейше?/', '');
  81.               $this->s($RV, '/нн$/', 'н');
  82.           }
  83.  
  84.           $stem = $start.$RV;
  85.         } while(false);
  86.         if ($this->Stem_Caching) $this->Stem_Cache[$word] = $stem;
  87.         return $stem;
  88.     }
  89.  
  90.     private function stem_caching($parm_ref)
  91.     {
  92.         $caching_level = @$parm_ref['-level'];
  93.         if ($caching_level) {
  94.             if (!$this->m($caching_level, '/^[012]$/')) {
  95.                 die(__CLASS__ . "::stem_caching() - Legal values are '0','1' or '2'. '$caching_level' is not a legal value");
  96.             }
  97.             $this->Stem_Caching = $caching_level;
  98.         }
  99.         return $this->Stem_Caching;
  100.     }
  101.  
  102.     public function clear_stem_cache()
  103.     {
  104.         $this->Stem_Cache = array();
  105.     }
  106. }
  107.  


теперь на входе можно принимать строку:

PHP:
скопировать код в буфер обмена
  1. echo $stemmer->stem_string('Дождливыми вечерами мы читали книги под лампой');//дождлив вечер мы чита книг ламп


Также из строки будут удалены союзы и предлоги (при установке флага $unset_predlog в true) перечисленные в:

PHP:
скопировать код в буфер обмена
  1. private $PREDLOG = '/(^|\s)(и|для|в|на|под|из|с|по)(\s|$)/u';


Пример использования:

PHP:
скопировать код в буфер обмена
  1. $stemmer = new Lingua_Stem_Ru();
  2. echo $stemmer->stem_string('Дождливыми вечерами мы читали книги под лампой');//дождлив вечер мы чита книг ламп

(Отредактировано автором: 17 Ноября, 2011 - 10:20:33)



-----
Когда всматриваешься в тёмную бездну, учти, что кто-то может смотреть на тебя из неё...
 
My status
 Top
snikers987
Отправлено: 13 Ноября, 2011 - 17:10:18
Post Id



Участник


Покинул форум
Сообщений всего: 1239
Дата рег-ции: Сент. 2011  
Откуда: Крым


Помог: 25 раз(а)




Может быть кому пригодится=)


-----
Когда всматриваешься в тёмную бездну, учти, что кто-то может смотреть на тебя из неё...
 
My status
 Top
Данил_123
Отправлено: 13 Ноября, 2011 - 17:13:42
Post Id


Участник


Покинул форум
Сообщений всего: 1026
Дата рег-ции: Июнь 2011  
Откуда: rostov


Помог: 9 раз(а)




Много изменений внес?
Спойлер (Отобразить)

(Отредактировано автором: 13 Ноября, 2011 - 17:14:36)



-----
http://mysitecost.ru
 
 Top
snikers987
Отправлено: 13 Ноября, 2011 - 17:22:40
Post Id



Участник


Покинул форум
Сообщений всего: 1239
Дата рег-ции: Сент. 2011  
Откуда: Крым


Помог: 25 раз(а)




Данил_123 пишет:
Много изменений внес?
Спойлер (Отобразить)


Я и так написал что сделал.


-----
Когда всматриваешься в тёмную бездну, учти, что кто-то может смотреть на тебя из неё...
 
My status
 Top
Данил_123
Отправлено: 13 Ноября, 2011 - 17:27:49
Post Id


Участник


Покинул форум
Сообщений всего: 1026
Дата рег-ции: Июнь 2011  
Откуда: rostov


Помог: 9 раз(а)




snikers987 зачем выложил, вроде все сначала в гугле пасутся после тут.. Я написал название топика и подобных достаточно много


-----
http://mysitecost.ru
 
 Top
snikers987
Отправлено: 13 Ноября, 2011 - 17:32:09
Post Id



Участник


Покинул форум
Сообщений всего: 1239
Дата рег-ции: Сент. 2011  
Откуда: Крым


Помог: 25 раз(а)




Данил_123 пишет:
snikers987 зачем выложил, вроде все сначала в гугле пасутся после тут.. Я написал название топика и подобных достаточно много


Если бы все 'послись' сначала в гугле форум бы не был зас[sensored]т повторяющимися 20 раз нубовскими темами. И найти не сложно когда знаеш что ищешь, вот ты например знал об таком классе? Уверен что нет.


-----
Когда всматриваешься в тёмную бездну, учти, что кто-то может смотреть на тебя из неё...
 
My status
 Top
Данил_123
Отправлено: 13 Ноября, 2011 - 18:16:32
Post Id


Участник


Покинул форум
Сообщений всего: 1026
Дата рег-ции: Июнь 2011  
Откуда: rostov


Помог: 9 раз(а)




snikers987 нет не знал, спасибо почитал, и в гугле тоже.. Можно было выложить ссылку на источник..


-----
http://mysitecost.ru
 
 Top
Самогонщик
Отправлено: 15 Ноября, 2011 - 15:57:16
Post Id



Посетитель


Покинул форум
Сообщений всего: 495
Дата рег-ции: Окт. 2011  


Помог: 8 раз(а)




Полезный для меня материал, что-то он у меня плохо гуглился, а здесь случайно попался.
 
 Top
EuGen Администратор
Отправлено: 17 Ноября, 2011 - 08:40:19
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




snikers987
А класс написали Вы? Если нет, то прошу ознакомиться с правилами раздела. Мы относимся очень внимательно к таким публикациям. Если код не Ваш, то, пожалуйста, укажите первоисточники в первом сообщении темы.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
snikers987
Отправлено: 17 Ноября, 2011 - 10:18:20
Post Id



Участник


Покинул форум
Сообщений всего: 1239
Дата рег-ции: Сент. 2011  
Откуда: Крым


Помог: 25 раз(а)




Я не знаю где первоисточники на PHP, я не предендую на авторство, только мои правки, ссылку на проект Мартина Портера (разработчика алгоритма) добавил в первый пост. Вообще, удаляй тему за несоответствие правилам, для меня это не принципиально, хотел как лучше.

(Отредактировано автором: 17 Ноября, 2011 - 10:22:50)



-----
Когда всматриваешься в тёмную бездну, учти, что кто-то может смотреть на тебя из неё...
 
My status
 Top
EuGen Администратор
Отправлено: 17 Ноября, 2011 - 10:24:27
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Нет, почему же удалить. Согласно правилам это просто относится к обсуждению сторонних статей. Все в порядке. Благодарю за полезный материал.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
victordax
Отправлено: 28 Апреля, 2013 - 20:24:03
Post Id


Новичок


Покинул форум
Сообщений всего: 1
Дата рег-ции: Апр. 2013  


Помог: 0 раз(а)




snikers987 пишет:
От себя внес изменения и теперь все корректно работает с UTF-8.

Спасибо тебе огромное! Как долго я бился с этой кодировкой...выручил!
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Обсуждение статей »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB