从 PHP 的搜索字符串中删除停止词

bam*_*ole 4 php

我在优化 MySql 查询的搜索字符串时遇到了 PHP 函数的问题。

我需要通过搜索“the hobbit”来找到一个看起来像“hobbit, the”的条目。

我考虑过如果文章的搜索字符串中有尾随空格,则将其删除(在德国,我们有“der”、“die”和“das”)。

我的函数如下所示:

      public function optimizeSearchString($searchString)
      {
        $articles = [
          'der ',
          'die ',
          'das ',
          'the '
        ];
    
    
        foreach ($articles as $article) {
//only cut $article out of $searchString if its longer than the $article itself
          if (strlen($searchString) > strlen($article) && strpos($searchString, $article)) {
            $searchString = str_replace($article, '', $searchString);
            break;
          }
        }
    
        return $searchString;
      }
Run Code Online (Sandbox Code Playgroud)

但这不起作用...

也许使用正则表达式有更好的解决方案?

Jon*_*y 5 5

1.) 要使用正则表达式从字符串的开头或结尾删除一个停用词,如下所示

~^\W*(der|die|das|the)\W+\b|\b\W+(?1)\W*$~i
Run Code Online (Sandbox Code Playgroud)
  • ~模式分隔符
  • ^插入符号锚点匹配字符串的开头
  • \W(上)是字符的缩写,不是单词字符
  • (der|die|das|the)|第一个括号中的交替
  • \b匹配单词边界
  • 粘贴(?1)第一组的图案
  • $匹配字符串中最后一个字符之后的位置
  • 使用i (PCRE_CASELESS) 标志。如果输入是utf-8,还需要u (PCRE_UTF8)标志。

参考 - 这个正则表达式是什么意思

生成模式:

// array containing stopwords
$stopwords = array("der", "die", "das", "the");

// escape the stopword array and implode with pipe
$s = '~^\W*('.implode("|", array_map("preg_quote", $stopwords)).')\W+\b|\b\W+(?1)\W*$~i';

// replace with emptystring
$searchString = preg_replace($s, "", $searchString);
Run Code Online (Sandbox Code Playgroud)

请注意,如果数组~中出现分隔符$stopwords,则还必须使用反斜杠对其进行转义。

PHP 测试位于 eval.in正则表达式模式位于 regex101


2.) 但是要删除字符串中任意位置的停用词,如何拆分为单词:

// words to be removed
$stopwords = array(
'der' => 1,
'die' => 1,
'das' => 1,
'the' => 1);
# used words as key for better performance

// remove stopwords from string
function strip_stopwords($str = "")
{
  global $stopwords;

  // 1.) break string into words
  // [^-\w\'] matches characters, that are not [0-9a-zA-Z_-']
  // if input is unicode/utf-8, the u flag is needed: /pattern/u
  $words = preg_split('/[^-\w\']+/', $str, -1, PREG_SPLIT_NO_EMPTY);

  // 2.) if we have at least 2 words, remove stopwords
  if(count($words) > 1)
  {
    $words = array_filter($words, function ($w) use (&$stopwords) {
      return !isset($stopwords[strtolower($w)]);
      # if utf-8: mb_strtolower($w, "utf-8")
    });
  }

  // check if not too much was removed such as "the the" would return empty
  if(!empty($words))
    return implode(" ", $words);
  return $str;
}
Run Code Online (Sandbox Code Playgroud)

请参阅eval.in 、ideone.com上的演示

// test it
echo strip_stopwords("The Hobbit das foo, der");
Run Code Online (Sandbox Code Playgroud)

霍比特人福

此解决方案还将删除所有标点符号,因为在删除常用单词_ - '后,它会用空格内爆剩余的单词。这个想法是为查询准备字符串。

两种解决方案都不会修改大小写,并且如果字符串仅包含一个 stopword ,则会保留该字符串。

常用词列表