TopList Яндекс цитирования
Русский переплет
Портал | Содержание | О нас | Авторам | Новости | Первая десятка | Дискуссионный клуб | Чат Научный форум
Первая десятка "Русского переплета"
Темы дня:

Мир собирается объявить бесполётную зону в нашей Vselennoy! | Президенту Путину о создании Института Истории Русского Народа. |Нас посетило 40 млн. человек | Чем занимались русские 4000 лет назад? | Кому давать гранты или сколько в России молодых ученых?



всякие разные перловые заметки

Как реализовать релевантность и поиск по числу слов

Задача, сделать поисковик чтобы оценивал похожесть, степень одинаковости предложений и текста. Эту задачу более менее реализует приведенный ниже скрипт:

#!/usr/bin/perl -w
use locale;

 %oo=("будет"=>1, "африка"=>1, "завтра"=>1);

$b="африка африка будет завтра африка";
$o="африка будет урааа зачем африка";
$tw="африка небудет вчера будет завтра";
$tb="аляска аляска будет будет будет сегодня";

@m=($b, $o, $tb, $tw); rrand(\@m);
print join "\n", @m,"\n";

for $i(0 .. $#m){
  $h{$i}{$1}++ while $m[$i]=~m!((\w[\w-]*){4,30})!g;
  $vr{$i}=$m[$i];
}

for $r(keys %h){print "\n"; 
  my (@ee, $u, $trr);
  for $n(keys %{$h{$r}}){
    do{
      $t = join " " => $vr{$r};
      $u+=1;
      push @ee => $h{$r}{$n};
    } if exists $oo{$n};
  } 
  print "$t ",$u + $ee[0]-1,"\n";
}

sub rrand{
  my $m = shift; my $i;
  for($i=@$m; --$i;){
    my $j = int rand($i+1);
    next if $i==$j;
    @$m[$i,$j] = @$m[$j,$i]
  }
}

есть какой-то текст в переменнах $b,$o,$tw,$tb, загоняется все в массив. Для отладки пишется подпрограмма rrand(), которая переставляет случаным образом элементы массива. Далее идет цикл, подсчитывающий частоты одинаковых слов в переменных и заносящий эти частоты в хеш хешей. Регулярное выражение while $m[$i]=~m!((\w[\w-]*){4,30})!g; вырезает по одному слову через пробел, причем ширина слова не менее 4 букв и не более 30. В силу действия модификатора g работает цикл, заполняющий хэш хешей. В хеше хешей 1(т.к. нуумерация элементов массива была случаный образом изменена, то удобно обращаться через номер массива) содержатся предположим для переменной $b такие данные:

     $b = "африка африка будет завтра африка";

     $h{1}=(
            "африка" => 3,
            "будет" => 1,
            "завтра" => 1
           ); 

т.е. слово африка по частоте употребления в три раза больше в файле, что дает ему большие шансы вылезти в список перых результатов. Далее следуют слова будет и завтра, которые так-же играют немаловажную роль в поднятии ссылки наверх из результатов поискового запроса. Далее в цикле объявляется хеш(задача была сделать, а не память сэкономить), который будет выводить результаты запроса.

Далее идет цикл:

     for $r(keys %h){print "\n";
       my (@ee, $u, $trr);
       for $n(keys %{$h{$r}}){
         do{
           $t = join " " => $vr{$r};
           $u++;
           push @ee => $h{$r}{$n};
         } if exists $oo{$n};
       } 
       print "$t ",$u + $ee[0]-1,"\n";
     }

запрашиваем численное название хеша в переменную $r, считываем с её помощью хеши хешей. Здесь функцией exists реализован поиск общих ключей в двух хешах: в хеше, поступающем на ввод, и текущем по шагу цикла хеше хешей. Если информация содержится в начальном втором хеше %vr, то запрашиваем её $vr{$r}. Строчка $u++ отвечает за количество вхождений всех слов, заданных в запросе, в искомую строку(файл). Допустим на входе фраза "будет африка завтра", если хотя бы одно слово из этой фразы совпало со словом в очередной строке(ведь изначально строка была побита на частотный хеш) то локальная переменная $u увеличит свое значение на единичку. Если два слова в строке и в запросе одинаковы, то $u=2, если три - $u=3 и так далее, слов в запросе может быть любое количество. Далее идет строчка

     push @ee => $h{$r}{$n};

которая заносит частоты слов(3,1,1 как было выше в примере) в текущей строке. Дальше идет сама exists и после неё разбираемся с весом повторяющихся слов и весом полных совпадений. Т.е. должно быть так, чтобы полное совпадение фразы имело большее значение, нежели чем неполное совпадение + пара повторов. Но функция федет себя по хитрому, допустим, если нужно найти специализированную информацию типа "Хеш хешей хешей хешей хешей массивов", то вес повторений слов будет больше, т.е. вклад члена $ee[0]-1(разница в единицах на случай непреднамеренного повтора) больше, чем $u. В то-же время частота повторений может запросто вывести наверх ссылку с словом, которому посвящен текст. Т.е. некий баланс для фраз, повторений и одиночных слов.


Rambler's Top100