如何检查一个string是否包含特定的单词?

考虑:

$a = 'How are you?'; if ($a contains 'are') echo 'true'; 

假设我有上面的代码,写入语句if ($a contains 'are')的正确方法if ($a contains 'are')什么?

你可以使用strpos()函数来查找一个string在另一个string中的出现:

 $a = 'How are you?'; if (strpos($a, 'are') !== false) { echo 'true'; } 

请注意,使用!== false是故意的; strpos()返回干草string中针串开始的偏移量,如果没有find针,则返回布尔值false 。 由于0是一个有效的偏移量,0是“falsey”,我们不能使用像!strpos($a, 'are')这样简单的结构。

你可以使用正则expression式。 它看起来像这样:

 $a = 'How are you?'; if (preg_match('/are/',$a)) echo 'true'; 

别告诉我,因为你以前听说过这是不好的。 如果您有任何事实可以支持,则可以;)

在性能方面,速度提高了三倍,记住,当我做了一百万次比赛的时候,比赛结束花费了1.5秒,而花费了0.5秒。 我想说的是,它运行速度非常快。 如果你每秒没有10万游客,你不应该关心这种东西,并采取什么是最舒服的,国际海事组织。

使用strposfunction:

 if (strpos($a, 'are') !== false) echo 'true'; 

这是一个小实用程序function,在这种情况下很有用

 // returns true if $needle is a substring of $haystack function contains($needle, $haystack) { return strpos($haystack, $needle) !== false; } 

虽然这些答案中的大部分都会告诉你一个string是否出现在你的string中,但是如果你正在寻找一个特定的单词 ,而不是一个string,那通常不是你想要的。

有什么不同? 子字符可以出现在另一个字里面:

  • “区域”开始的“是”
  • “野兔”结束时的“是”
  • 在“票价”中间的“是”

减轻这种情况的一种方法是使用一个正则expression式与字边界 ( \b )相结合:

 function containsWord($str, $word) { return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str); } 

这种方法没有上面提到的相同的误报,但它确实有一些自己的边缘情况。 单词边界与非单词字符( \W )匹配,这些字符将不是azAZ0-9_ 。 这意味着数字和下划线将被视为单词字符,像这样的情况将失败:

  • “你在想什么?”中的“是”
  • 在“你不知道这些是什么?

如果你想要比这更准确的东西,你将不得不开始进行英语语法分析,这是一个相当大的蠕虫jar(并假设适当的语法使用,总之并不总是给定的)。

要确定一个string是否包含另一个string,可以使用PHP函数strpos() 。

int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )

 <?php $haystack = 'how are you'; $needle = 'are'; if (strpos($haystack,$needle) !== false) { echo '$haystack contains $needle'; } ?> 

警告:

如果你正在search的针在干草堆的开始,它将返回位置0,如果你做一个==比较,这将无法正常工作,你将需要做一个===

==符号是一个比较,并testing左侧的variables/expression式/常量是否与右侧的variables/expression式/常量具有相同的值。

一个===符号是一个比较,看看两个variables/expression式/常量是否相等AND并具有相同的types – 即都是string或两者都是整数。

使用strstr()stristr()如果您的search应该是不区分大小写的是另一种select。

看看strpos()

 <?php $mystring = 'abc'; $findme = 'a'; $pos = strpos($mystring, $findme); // Note our use of ===. Simply, == would not work as expected // because the position of 'a' was the 0th (first) character. if ($pos === false) { echo "The string '$findme' was not found in the string '$mystring'."; } else { echo "The string '$findme' was found in the string '$mystring',"; echo " and exists at position $pos."; } ?> 

如果你想避免“falsey”和“truthy”的问题,你可以使用substr_count:

 if (substr_count($a, 'are') > 0) { echo "at least one 'are' is present!"; } 

它比strpos慢一点,但是避免了比较问题。

使用stripos()使用不区分大小写匹配

 if (stripos($string,$stringToSearch) !== false) { echo 'true'; } 

另一个select是使用strstr()函数。 就像是:

 if (strlen(strstr($haystack,$needle))>0) { // Needle Found } 

注意点:strstr()函数区分大小写。 对于不区分大小写的search,请使用stristr()函数。

同行SamGoody和乐高Stormtroopr评论。

如果您正在寻找一种基于多个单词的邻近性/相关性search结果进行排名的PHPalgorithm,那么只需使用PHP即可快速简单地生成search结果:

其他布尔search方法sush as strpos()preg_match()strstr()stristr()

  1. 不能search多个单词
  2. 结果是没有排名的

基于向量空间模型和tf-idf(词频 – 逆文档频率)的 PHP方法:

这听起来很难,但是却非常容易。

如果我们想要在一个string中search多个单词,核心问题是我们如何给每个单词分配一个权重?

如果我们可以根据string作为一个整体的代表性来对string进行加权,那么我们可以通过与查询最匹配的结果来sorting结果。

这是向量空间模型的思想, 离SQL全文search的工作方式不远了:

 function get_corpus_index($corpus = array(), $separator=' ') { $dictionary = array(); $doc_count = array(); foreach($corpus as $doc_id => $doc) { $terms = explode($separator, $doc); $doc_count[$doc_id] = count($terms); // tf–idf, short for term frequency–inverse document frequency, // according to wikipedia is a numerical statistic that is intended to reflect // how important a word is to a document in a corpus foreach($terms as $term) { if(!isset($dictionary[$term])) { $dictionary[$term] = array('document_frequency' => 0, 'postings' => array()); } if(!isset($dictionary[$term]['postings'][$doc_id])) { $dictionary[$term]['document_frequency']++; $dictionary[$term]['postings'][$doc_id] = array('term_frequency' => 0); } $dictionary[$term]['postings'][$doc_id]['term_frequency']++; } //from http://phpir.com/simple-search-the-vector-space-model/ } return array('doc_count' => $doc_count, 'dictionary' => $dictionary); } function get_similar_documents($query='', $corpus=array(), $separator=' '){ $similar_documents=array(); if($query!=''&&!empty($corpus)){ $words=explode($separator,$query); $corpus=get_corpus_index($corpus, $separator); $doc_count=count($corpus['doc_count']); foreach($words as $word) { if(isset($corpus['dictionary'][$word])){ $entry = $corpus['dictionary'][$word]; foreach($entry['postings'] as $doc_id => $posting) { //get term frequency–inverse document frequency $score=$posting['term_frequency'] * log($doc_count + 1 / $entry['document_frequency'] + 1, 2); if(isset($similar_documents[$doc_id])){ $similar_documents[$doc_id]+=$score; } else{ $similar_documents[$doc_id]=$score; } } } } // length normalise foreach($similar_documents as $doc_id => $score) { $similar_documents[$doc_id] = $score/$corpus['doc_count'][$doc_id]; } // sort fro high to low arsort($similar_documents); } return $similar_documents; } 

情况1

 $query = 'are'; $corpus = array( 1 => 'How are you?', ); $match_results=get_similar_documents($query,$corpus); echo '<pre>'; print_r($match_results); echo '</pre>'; 

结果

 Array ( [1] => 0.52832083357372 ) 

情况2

 $query = 'are'; $corpus = array( 1 => 'how are you today?', 2 => 'how do you do', 3 => 'here you are! how are you? Are we done yet?' ); $match_results=get_similar_documents($query,$corpus); echo '<pre>'; print_r($match_results); echo '</pre>'; 

结果

 Array ( [1] => 0.54248125036058 [3] => 0.21699250014423 ) 

情况3

 $query = 'we are done'; $corpus = array( 1 => 'how are you today?', 2 => 'how do you do', 3 => 'here you are! how are you? Are we done yet?' ); $match_results=get_similar_documents($query,$corpus); echo '<pre>'; print_r($match_results); echo '</pre>'; 

结果

 Array ( [3] => 0.6813781191217 [1] => 0.54248125036058 ) 

有很多的改进,但是模型提供了一种从自然查询中获得好结果的方式,它没有像strpos()preg_match()strstr()或者stristr()那样的布尔运算符stristr()

NOTA BENE

在search单词之前可select地消除冗余

  • 从而减小索引尺寸并导致较less的存储需求

  • 减less磁盘I / O

  • 更快的索引和更快的search。

1.标准化

  • 将所有文本转换为小写

2.停止单词消除

  • 消除文本中没有真正含义的词语(如“和”,“或”,“为”等)

3.字典replace

  • 用其他具有相同或相似含义的词语replace。 (例如:用“饥饿”取代“饥饿”和“饥饿”的例子)

  • 进一步的algorithm措施(雪球)可能会进一步减less单词的本质含义。

  • 用hex等值replace颜色名称

  • 通过降低精度来减less数值是使文本标准化的其他方式。

资源

我有点印象深刻,没有任何使用strposstrstr和类似的函数提到的多字节string函数 (2015-05-08)的答案。

基本上,如果您在查找包含德语,法语,葡萄牙语,西class牙语等某些语言的字符时遇到问题 (例如: äéôçºñ ),您可能需要优先与mb_的function。 因此,接受的答案将使用mb_strposmb_stripos (对于不区分大小写的匹配):

 if (mb_strpos($a,'are') !== false) { echo 'true'; } 

如果您不能保证UTF-8中的所有数据都是100% ,那么您可能需要使用mb_函数。

一个很好的文章来理解为什么绝对最小每个软件开发人员肯定,积极必须知道Unicode和字符集(无借口!)乔尔Spolsky

下面的function也起作用,不依赖于其他function; 它只使用原生的PHPstring操作。 就个人而言,我不build议这样做,但你可以看到它是如何工作的:

 <?php if (!function_exists('is_str_contain')) { function is_str_contain($string, $keyword) { if (empty($string) || empty($keyword)) return false; $keyword_first_char = $keyword[0]; $keyword_length = strlen($keyword); $string_length = strlen($string); // case 1 if ($string_length < $keyword_length) return false; // case 2 if ($string_length == $keyword_length) { if ($string == $keyword) return true; else return false; } // case 3 if ($keyword_length == 1) { for ($i = 0; $i < $string_length; $i++) { // Check if keyword's first char == string's first char if ($keyword_first_char == $string[$i]) { return true; } } } // case 4 if ($keyword_length > 1) { for ($i = 0; $i < $string_length; $i++) { /* the remaining part of the string is equal or greater than the keyword */ if (($string_length + 1 - $i) >= $keyword_length) { // Check if keyword's first char == string's first char if ($keyword_first_char == $string[$i]) { $match = 1; for ($j = 1; $j < $keyword_length; $j++) { if (($i + $j < $string_length) && $keyword[$j] == $string[$i + $j]) { $match++; } else { return false; } } if ($match == $keyword_length) { return true; } // end if first match found } // end if remaining part } else { return false; } // end for loop } // end case4 } return false; } } 

testing:

 var_dump(is_str_contain("test", "t")); //true var_dump(is_str_contain("test", "")); //false var_dump(is_str_contain("test", "test")); //true var_dump(is_str_contain("test", "testa")); //flase var_dump(is_str_contain("a----z", "a")); //true var_dump(is_str_contain("a----z", "z")); //true var_dump(is_str_contain("mystringss", "strings")); //true 
 if (preg_match('are', $a)) { echo 'true'; } 

我遇到了一些麻烦,最后我select了自己的解决scheme。 不使用正则expression式引擎:

 function contains($text, $word) { $found = false; $spaceArray = explode(' ', $text); $nonBreakingSpaceArray = explode(chr(160), $text); if (in_array($word, $spaceArray) || in_array($word, $nonBreakingSpaceArray) ) { $found = true; } return $found; } 

您可能会注意到,以前的解决scheme不是用作另一个词的前缀的答案。 为了使用你的例子:

 $a = 'How are you?'; $b = "a skirt that flares from the waist"; $c = "are"; 

对于上面的示例, $a$b包含$c ,但是您可能希望函数告诉您只有$a包含$c

你可以使用strstr函数:

 $haystack = "I know programming"; $needle = "know"; $flag = strstr($haystack, $needle); if ($flag){ echo "true"; } 

不使用内置function:

 $haystack = "hello world"; $needle = "llo"; $i = $j = 0; while (isset($needle[$i])) { while (isset($haystack[$j]) && ($needle[$i] != $haystack[$j])) { $j++; $i = 0; } if (!isset($haystack[$j])) { break; } $i++; $j++; } if (!isset($needle[$i])) { echo "YES"; } else{ echo "NO "; } 

你应该使用大小写不敏感的格式,所以如果input的数值small或大小写不重要。

 <?php $grass = "This is pratik joshi"; $needle = "pratik"; if (stripos($grass,$needle) !== false) { /*If i EXCLUDE : !== false then if string is found at 0th location, still it will say STRING NOT FOUND as it will return '0' and it will goto else and will say NOT Found though it is found at 0th location.*/ echo 'Contains word'; }else{ echo "does NOT contain word"; } ?> 

这里stripos发现针在heystack 考虑案件(小/帽)。

带输出的PHPCode样本

短手版本

 $result = false!==strpos($a, 'are'); 

为了find一个“单词”,而不是发生一系列可能实际上是另一个单词的一部分的字母,以下是一个很好的解决scheme。

 $string = 'How are you?'; $array = explode(" ", $string); if (in_array('are', $array) ) { echo 'Found the word'; } 

使用strstr()和stristr()从string中查找单词出现的另一个选项如下所示:

 <?php $a = 'How are you?'; if (strstr($a,'are')) // Case sensitive echo 'true'; if (stristr($a,'are')) // Case insensitive echo 'true'; ?> 
 $a = 'how are you'; if (strpos($a,'are')) { echo 'true'; } 

这可以通过三种不同的方式来完成:

  $a = 'How are you?'; 

1- stristr()

  if (strlen(stristr($a,"are"))>0) { echo "true"; // are Found } 

2 strpos()

  if (strpos($a, "are") !== false) { echo "true"; // are Found } 

3- preg_match()

  if( preg_match("are",$a) === 1) { echo "true"; // are Found } 

也许你可以使用这样的东西:

 <?php findWord('Test all OK'); function findWord($text) { if (strstr($text, 'ok')) { echo 'Found a word'; } else { echo 'Did not find a word'; } } ?> 

如果您只想检查一个string是否包含在另一个string中,请不要使用preg_match() 。 使用strpos()strstr()来代替,因为它们会更快。 ( http://in2.php.net/preg_match

 if (strpos($text, 'string_name') !== false){ echo 'get the string'; } 

在PHP中,validationstring是否包含特定子string的最佳方法是使用如下所示的简单帮助函数:

 function contains($haystack, $needle, $caseSensitive = false) { return $caseSensitive ? (strpos($haystack, $needle) === FALSE ? FALSE : TRUE): (stripos($haystack, $needle) === FALSE ? FALSE : TRUE); } 

说明:

  • strpos在string中查找第一次出现区分大小写的子string的位置。
  • striposstripos查找第一次出现不区分大小写的子string的位置。
  • myFunction($haystack, $needle) === FALSE ? FALSE : TRUE myFunction($haystack, $needle) === FALSE ? FALSE : TRUE确保myFunction总是返回一个布尔值,并在子串的索引为0时修复意外的行为。
  • $caseSensitive ? A : B $caseSensitive ? A : B根据$caseSensitive的值selectstrposstripos来完成工作。

输出:

 var_dump(contains('bare','are')); // Outputs: bool(true) var_dump(contains('stare', 'are')); // Outputs: bool(true) var_dump(contains('stare', 'Are')); // Outputs: bool(true) var_dump(contains('stare', 'Are', true)); // Outputs: bool(false) var_dump(contains('hair', 'are')); // Outputs: bool(false) var_dump(contains('aren\'t', 'are')); // Outputs: bool(true) var_dump(contains('Aren\'t', 'are')); // Outputs: bool(true) var_dump(contains('Aren\'t', 'are', true)); // Outputs: bool(false) var_dump(contains('aren\'t', 'Are')); // Outputs: bool(true) var_dump(contains('aren\'t', 'Are', true)); // Outputs: bool(false) var_dump(contains('broad', 'are')); // Outputs: bool(false) var_dump(contains('border', 'are')); // Outputs: bool(false) 

您需要使用相同/不相同的运算符,因为strpos可以返回0,因为它是索引值。 如果你喜欢三元运算符,可以考虑使用以下(稍后我会承认):

 echo FALSE === strpos($a,'are') ? 'false': 'true'; 

如果你想检查string是否包含几个特定的​​单词,你可以这样做:

 $badWords = array("dette", "capitale", "rembourser", "ivoire", "mandat"); $string = "a string with the word ivoire"; $matchFound = preg_match_all("/\b(" . implode($badWords,"|") . ")\b/i", $string, $matches); if ($matchFound) { echo "a bad word has been found"; } else { echo "your string is okay"; } 

例如,在发送电子邮件时避免垃圾邮件很有用。

strpos函数可以正常工作,但是如果您想对段落中的单词进行case-insensitive检查,那么您可以使用PHPstripos函数。

例如,

 $result = stripos("I love PHP, I love PHP too!", "php"); if ($result === false) { // Word does not exist } else { // Word exists } 

在string中查找第一次出现不区分大小写的子string的位置。

如果该字不存在于string中,则返回false,否则返回该字的位置。

检查string是否包含特定字词?

这意味着string必须被parsing为单词(参见下面的注释)。

做到这一点,并指定分隔符的一种方法是使用preg_split ( doc ):

 <?php function contains_word($str, $word) { // split string into words // separators are substrings of at least one non-word character $arr = preg_split('/\W+/', $str, NULL, PREG_SPLIT_NO_EMPTY); // now the words can be examined each foreach ($arr as $value) { if ($value === $word) { return true; } } return false; } function test($str, $word) { if (contains_word($str, $word)) { echo "string '" . $str . "' contains word '" . $word . "'\n"; } else { echo "string '" . $str . "' does not contain word '" . $word . "'\n" ; } } $a = 'How are you?'; test($a, 'are'); test($a, 'ar'); test($a, 'hare'); ?> 

运行给出

 $ php -f test.php string 'How are you?' contains word 'are' string 'How are you?' does not contain word 'ar' string 'How are you?' does not contain word 'hare' 

注意:这里我们不是指每一个符号序列的词。

词的实际定义是PCRE正则expression式引擎,其中词是仅由单词字符组成的子string,由非单词字符分隔。

“单词”字符是任何字母或数字或下划线字符,即可以是Perl“单词”的一部分的任何字符。 字母和数字的定义是由PCRE的字符表来控制的,并且如果特定于语言环境的匹配正在发生(..)