Сравните слова, также нужно искать множественное число и ING? - PullRequest
5 голосов
/ 06 декабря 2010

У меня есть два списка слов, предположим, LIST1 и LIST2. Я хочу сравнить LIST1 с LIST2, чтобы найти дубликаты, но он также должен найти множественное число слова и форму. Например.

Предположим, что в LIST1 есть слово "account", а в LIST2 есть слова "account, accounting". Когда я сравниваю, результат должен показывать два совпадения для слова "account".

Я делаю это на PHP и у меня есть СПИСОК в таблицах mysql.

Ответы [ 5 ]

5 голосов
/ 06 декабря 2010

Вы можете использовать технику, называемую porter stemming , чтобы сопоставить каждую запись списка со своей основой, а затем сравнить основы. Реализацию алгоритма Портера Стемминга в PHP можно найти здесь или здесь .

0 голосов
/ 19 апреля 2016

Вы можете рассмотреть возможность использования Doctrine Inflector в сочетании с stemmer для этого.

Вот алгоритм на высоком уровне

  1. Разделить строку поиска по пробелам, обрабатывать слова по отдельности
  2. Строчные слова для поиска
  3. Полосатые специальные символы
  4. Singularize, заменить различную часть на подстановочный знак ('%')
  5. Стебель, заменить отличающуюся часть подстановочным знаком ('%')

Вот функция, которую я собрал

/**
 * Use inflection and stemming to produce a good search string to match subtle
 * differences in a MySQL table.
 *
 * @string $sInputString The string you want to base the search on
 * @string $sSearchTable The table you want to search in
 * @string $sSearchField The field you want to search
 */
function getMySqlSearchQuery($sInputString, $sSearchTable, $sSearchField)
{
    $aInput  = explode(' ', strtolower($sInputString));
    $aSearch = [];
    foreach($aInput as $sInput) {
        $sInput = str_replace("'", '', $sInput);

        //--------------------
        // Inflect
        //--------------------
        $sInflected = Inflector::singularize($sInput);

        // Otherwise replace the part of the inflected string where it differs from the input string
        // with a % (wildcard) for the MySQL query
        $iPosition = strspn($sInput ^ $sInflected, "\0");

        if($iPosition !== null && $iPosition < strlen($sInput)) {
            $sInput = substr($sInflected, 0, $iPosition) . '%';
        } else {
            $sInput = $sInput;
        }

        //--------------------
        // Stem
        //--------------------
        $sStemmed = stem_english($sInput);

        // Otherwise replace the part of the inflected string where it differs from the input string
        // with a % (wildcard) for the MySQL query
        $iPosition = strspn($sInput ^ $sStemmed, "\0");

        if($iPosition !== null && $iPosition < strlen($sInput)) {
            $aSearch[] = substr($sStemmed, 0, $iPosition) . '%';
        } else {
            $aSearch[] = $sInput;
        }
    }

    $sSearch = implode(' ', $aSearch);
    return "SELECT * FROM $sSearchTable WHERE LOWER($sSearchField) LIKE '$sSearch';";
}

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

Input String: Mary's Hamburgers
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'mary% hamburger%';

Input String: Office Supplies
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'offic% suppl%';

Input String: Accounting department
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'account% depart%';

Возможно, не идеально, но в любом случае это хорошее начало! Где он упадет, это когда несколько совпадений будут возвращены. Там нет логики, чтобы определить лучший матч. Вот где могут появиться такие вещи, как полный текст MySQL и Lucene . Подумав немного подробнее, вы можете использовать levenshtein для ранжирования нескольких результатов с помощью этого подхода !

0 голосов
/ 06 декабря 2010

Эта функция выведет множественное число слова.

http://www.exorithm.com/algorithm/view/pluralize

Нечто подобное можно написать для герундов и причастий (форм)

0 голосов
/ 06 декабря 2010

Проблема в том, что, по крайней мере, на английском языке множественное число не является стандартным расширением и не является причастием. Вы можете сделать приближение, используя все слова +'ing' и +'s', но это даст ложные и отрицательные результаты.

Вы можете обработать это напрямую в MySQL, если хотите.

SELECT DISTINCT l2.word
  FROM LIST1 l1, LIST l2
  WHERE l1.word = l2.word OR l1.word + 's' = l2.word OR l1.word + 'ing' = l2.word;
0 голосов
/ 06 декабря 2010

Я бы взял ваше слово и сравнил его непосредственно со списком LIST2 и в то же время удалил ваше слово из каждого сравниваемого вами слова в поисках пропущенных слов, чтобы обозначить множественное число или слово (это должно быть достаточно точным).Если нет, вам придется сгенерировать алгоритм для создания множественного числа из слов, поскольку он не так прост, как добавление S.

Duplicate Ending List
s
es
ing

LIST1
Gas
Test

LIST2
Gases
Tests
Testing

Теперь сравните List1 с List2.В течение того же цикла сравнения проведите прямое сравнение с элементами, в котором слово из списка 1 будет удалено из текущего слова, которое вы просматриваете в списке 2. Теперь просто проверьте, есть ли этот результат в списке дубликатов конечного списка.

Надеюсь, что это имеет смысл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...