Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从PHP中的searchstring中删除停止词_Php - Fatal编程技术网

从PHP中的searchstring中删除停止词

从PHP中的searchstring中删除停止词,php,Php,我在使用php函数优化mssql查询的搜索字符串时遇到了问题 我需要通过搜索“霍比特人”来找到一个看起来像“霍比特人”的条目。 我考虑过如果搜索字符串后面有一个空格,就删掉这些文章(在德国我们有'der'、'die'和'das') 我的函数如下所示: public function optimizeSearchString($searchString) { $articles = [ 'der ', 'die ',

我在使用php函数优化mssql查询的搜索字符串时遇到了问题

我需要通过搜索“霍比特人”来找到一个看起来像“霍比特人”的条目。 我考虑过如果搜索字符串后面有一个空格,就删掉这些文章(在德国我们有'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;
      }
但这不起作用

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

1。)只需使用以下方法从字符串的开头或结尾删除一个停止字:

  • ~
  • ^
    插入符号与字符串开头匹配
  • \W
    (大写)表示字符,而不是
  • (在第一个括号中的| die | das | the)
    替换
    |
  • \b
  • (?1)
    粘贴第一组的图案
  • $
    匹配字符串中最后一个字符的后面
  • 已使用
    i
    (PCRE\u无壳)。如果输入为utf-8,还需要
    u
    (PCRE\u 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);
请注意,如果
~
分隔符出现在
$stopwords
数组中,则还必须使用反斜杠对其进行转义

,


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;
}
看,

霍比特人

此解决方案还将删除除
.
-
'
之外的任何标点符号,因为在删除常用词后,它会用空格内插剩余的词。其思想是为查询准备字符串

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

常用词列表

  • 维基百科
  • 维基百科

    • 由@Jonny 5提供的解决方案似乎是最适合我的解决方案

      现在我使用这样一个函数:

        public function optimizeSearchString($searchString = "")
        {
          $stopwords = array(
            'der' => 1,
            'die' => 1,
            'das' => 1,
            'the' => 1);
      
          $words = preg_split('/[^-\w\']+/', $searchString, -1, PREG_SPLIT_NO_EMPTY);
      
          if (count($words) > 1) {
            $words = array_filter($words, function ($v) use (&$stopwords) {
              return !isset($stopwords[strtolower($v)]);
            }
            );
          }
      
          if (empty($words)) {
            return $searchString;
          }
      
          return implode(" ", $words);
        }
      
      Jonny 5的新解决方案也会起作用,但我使用这个,因为我对正则表达式不太熟悉,我知道发生了什么:-)这就是我所做的

      public function optimizeSearchString($searchString) {
          $wordsFromSearchString = str_word_count($searchString, true);
          $finalWords = array_diff($wordsFromSearchString, $stopwords);
          return implode(" ", $finalWords);
      }
      

      我使用
      array_diff
      制作了一个不同的版本,@Yashrajsinh-Jadeja也这样做了。我添加了第三个参数“stracecmp”以忽略大小写,并使用简单的单词标记器将输入设置为数组

      //Search string with article
      $searchString = "Das blaue Haus"; //"The blue house"
      
      //Split string into array. (This method is insufficient and doesn't account for compound nouns like "blue jay" or "einfamilienhaus".)
      $wordArray = preg_split('/[^-\w\']+/', $searchString, -1, PREG_SPLIT_NO_EMPTY); 
      
      var_dump(optimizeSearchString($wordArray));
      
      function optimizeSearchString($wordArray) {
        $articles = array('der', 'die', 'das', 'the');
        $newArray = array_udiff($wordArray, $articles, 'strcasecmp');
        return $newArray;
      }
      
      输出:

      array(2) {
        [1]=>
        string(5) "blaue"
        [2]=>
        string(4) "Haus"
      }
      

      此测试
      strlen($searchString)>strlen($article)
      完全没有用,请删除它
      strpos
      可能返回解释为false的0。您必须编写
      strpos(…)!==错误
      。直接替换,而不是进行测试。在这里使用
      preg\u replace
      的优点是避免使用单词边界来分隔单词的误报,并使用交替在一次过程中删除所有单词。模式并不难,快速的正则表达式教程可以解决这个问题。@bambamboole查看并删除stopwords。对标题进行了编辑。请检查是否正常,否则撤消!你做得很好!真是太好了,这很有帮助!我还发布了另一个解决方案的答案:]您能解释一下为什么在第二个代码的
      array\u filter
      闭包中通过引用传递
      $stopwords
      ?我问的是关于价值与参考绩效的帖子。在这里传递值不是更好吗?看起来您只是复制了问题代码并重新发布了它。至少,您应该提供有关此代码的不同之处或它如何回答问题的上下文。
      //Search string with article
      $searchString = "Das blaue Haus"; //"The blue house"
      
      //Split string into array. (This method is insufficient and doesn't account for compound nouns like "blue jay" or "einfamilienhaus".)
      $wordArray = preg_split('/[^-\w\']+/', $searchString, -1, PREG_SPLIT_NO_EMPTY); 
      
      var_dump(optimizeSearchString($wordArray));
      
      function optimizeSearchString($wordArray) {
        $articles = array('der', 'die', 'das', 'the');
        $newArray = array_udiff($wordArray, $articles, 'strcasecmp');
        return $newArray;
      }
      
      array(2) {
        [1]=>
        string(5) "blaue"
        [2]=>
        string(4) "Haus"
      }
      
      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;
      }