Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Найти в массиве похожие элементы, русский текст, морфология 
:(
    Опции темы
Suppir
Дата 1.2.2010, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Имееются следующие элементы массива:

Аварийно-спасательная служба

Аварийно-спасательные службы

Спасатель

дисциплина труда спасателей

задачи аварийно-спасательных служб

заявка на предоставления субсидии

заявка на предоставления субсидий


...

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

Каким образом это можно реализовать, не прибегая к морфологическому анализу и сторонним библиотекам?


Это сообщение отредактировал(а) Suppir - 1.2.2010, 13:33
PM MAIL   Вверх
DurRandir
Дата 1.2.2010, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



Возможно, устроит расстояние Левенштейна?
PM   Вверх
Suppir
Дата 1.2.2010, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Да, то что нужно.

Вот алгоритм:

sub levenshtein($$){
  my @A=split //, lc shift;
  my @B=split //, lc shift;
  my @W=(0..@B);
  my ($i, $j, $cur, $next);
  for $i (0..$#A){
        $cur=$i+1;
        for $j (0..$#B){
                $next=min(
                        $W[$j+1]+1,
                        $cur+1,
                        ($A[$i] ne $B[$j])+$W[$j]
                );
                $W[$j]=$cur;
                $cur=$next;
        }
        $W[@B]=$next;
  }
  return $next;
}
 
sub min($$$){
  if ($_[0] < $_[2]){ pop @_; } else { shift @_; }
  return $_[0] < $_[1]? $_[0]:$_[1];
}

print levenshtein("Аварийно-спасательная служба","Аварийно-спасательные службы"); <>



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



PM MAIL   Вверх
klem4
Дата 1.2.2010, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 27.7.2008

Репутация: 2
Всего: 2



Ну во первых, на сколько я понял, этот алгоритм считает не просто кол-во различных символов, а 
Цитата

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


Во вторых надо все таки определить, как понимать похожесть строк, как вариант, можно использовать следующий алгоритм с применением ф-и Левенштейна:
Код

while (кол-во строк > 0)
{
   берем 1-ю строку;
  добавляем строку в новую(пустую) группу
  идем по остальным строкам:
  {
      разница между первой и текущей просматриваемой нас устраивает? -> да: добавляем эту строку в ГРУППУ похожих на первую и удаляем ее из массива
  }
  удаляем первую строку из массива
}

PM MAIL   Вверх
Suppir
Дата 2.2.2010, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Я думаю так:

если есть массив из элементов
1
2
3
4
5

то не обязательно делать перебор "все со всеми". Можно взять 1 в массив. Потом 2 и сравнить с 1. Потом 3 и сравнить с 2 и 1. И так далее. В общем, спасибо за советы!
PM MAIL   Вверх
amg
Дата 3.2.2010, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(Suppir @  1.2.2010,  15:46 Найти цитируемый пост)
Но если у меня несколько тысяч строк, то получается, что каждую строку нужно сравнивать с каждой строкой. Довольно долгий перебор получится.
Как одна из мер -- если длины строк сильно различаются, то проверять index'ом вхождение меньшей в бОльшую и бросать.

PM MAIL   Вверх
mvsgt
Дата 3.2.2010, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 27.3.2009

Репутация: 1
Всего: 1



попробуйте по первым нескольким символам слов сравнивать, например

"заявка на предоставления субсидии" => "занапрсу"

"заявочки на предоставления субсидий" => "занапрсу"

проблема обычно в окончаниях слов, иногда в порядке слов. Так можно немного уменьшить работу для алгоритма Ливенштейна. 
PM MAIL   Вверх
Suppir
Дата 4.2.2010, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



mvsgt, очень часто бывает, что ошибка состоит в том, что два слова "склеены":

заявка на предоставления субсидии
заявка напредоставления субсидии

Так что по началам слов здесь искать затруднительно. 


amg, "если длины строк сильно различаются, то проверять index'ом вхождение меньшей в бОльшую и бросать." - отличная идея, спасибо. 

p.s. Оказывается, всего ключей более 100 тыс.!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0736 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.