【问题标题】:Compare words, also need to look for plurals and ing?比较单词,还需要找复数和ing吗?
【发布时间】:2010-12-06 17:25:54
【问题描述】:

我有两个单词列表,假设 LIST1 和 LIST2。我想比较 LIST1 和 LIST2 以找到重复项,但它也应该找到单词的复数形式以及 ing 形式。例如。

假设 LIST1 有单词“account”,而 LIST2 有单词“accounts,accounting” 当我进行比较时,结果应该显示单词“account”的两个匹配项。

我在 PHP 中做,并且在 mysql 表中有 LIST。

【问题讨论】:

  • 我知道这是一个旧线程,但我只是添加了一个答案,如果你有时间看看你的想法。

标签: php mysql regex search


【解决方案1】:

您可以使用一种称为porter stemming 的技术将每个列表条目映射到其词干,然后比较这些词干。在 PHP 中 Porter Stemming 算法的实现可以在 herehere 找到。

【讨论】:

  • 不错。以前从未听说过这种技术。
  • 这就是为什么它刚刚出现在我的研究列表中。据我所知,它非常简单
  • 感谢算法。很高兴知道。但这并不是在所有情况下都有效,例如“办公用品”改为“办公用品”,“满屋”改为“满屋”以及许多其他问题。
  • 然后看看更一般的词干主题。 Porter 词干被认为是最好的英语词干算法之一,但它只是众多算法中的一种。维基百科有一个关于这个主题的完整页面en.wikipedia.org/wiki/Stemming
  • 我想添加another option,有一个原生扩展可以处理除英语之外的其他语言,而且速度可能相当快。
【解决方案2】:

我要做的是将您的单词直接与 LIST2 进行比较,同时从您要比较的每个单词中删除您的单词,寻找剩余的 ing、s、es 来表示复数或 ing 单词(这应该足够准确)。如果不是,您将不得不生成一个算法来使单词复数,因为它不像添加 S 那样简单。

Duplicate Ending List
s
es
ing

LIST1
Gas
Test

LIST2
Gases
Tests
Testing

现在比较 List1 和 List2。在同一个比较循环中,对项目进行直接比较,其中从列表 1 中的单词从列表 2 中您正在查看的当前单词中删除。现在只需检查此结果是否在重复结尾列表中。

希望这是有道理的。

【讨论】:

    【解决方案3】:

    问题在于,至少在英语中,复数并不都是标准扩展,现在分词也不是。您可以使用所有单词 +'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;
    

    【讨论】:

      【解决方案4】:

      这个函数会输出一个单词的复数形式。

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

      可以为动名词和现在分词(ing 形式)写类似的东西

      【讨论】:

      • 感谢 Mike C,这个脚本简单易懂,帮助我获得了一些想法
      【解决方案5】:

      为此,您可以考虑将Doctrine Inflector 类与stemmer 结合使用。

      这是高层次的算法

      1. 在空格上拆分搜索字符串,单独处理单词
      2. 搜索词小写
      3. 去除特殊字符
      4. 单数化,用通配符 ('%') 替换 differing portion
      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 fulltextLucene 之类的东西的用武之地。再想一想,您也许可以使用levenshtein 来通过这种方法对多个结果进行排名!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-23
        • 1970-01-01
        • 2022-11-03
        • 2021-09-20
        • 1970-01-01
        相关资源
        最近更新 更多