php substring




如何检查字符串是否包含特定单词? (20)

考虑:

$a = 'How are you?';

if ($a contains 'are')
    echo 'true';

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


检查字符串是否包含特定单词?

这意味着必须将字符串解析为单词(请参阅下面的注释)。

执行此操作和指定分隔符的一种方法是使用preg_splitdoc ):

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

跑步给出了

<?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');

?>

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

词的实际定义在某种意义上是PCRE正则表达式引擎,其中单词是仅由单词字符组成的子串,由非单词字符分隔。

“单词”字符是任何字母或数字或下划线字符,即任何可以成为Perl“单词”一部分的字符。 字母和数字的定义由PCRE的字符表控制,如果发生特定于语言环境的匹配,则可能会有所不同(..)


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

例如,

$ 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'

查找字符串中第一次出现不区分大小写的子字符串的位置。

如果字符串中不存在该单词,则它将返回false,否则它将返回该单词的位置。


为了找到一个“单词”,而不是一系列可能实际上是另一个单词的一部分的字母的出现,以下将是一个很好的解决方案。

$string = 'How are you?';
$array = explode(" ", $string);

if (in_array('are', $array) ) {
    echo 'Found the word';
}

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

<?php
    findWord('Test all OK');

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

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

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

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

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

可以使用以下函数检查字符串:

function either_String_existor_not($str, $character) {
    if (strpos($str, $character) !== false) {
        return true;
    }
    return false;
}

同意SamGoody和Lego Stormtroopr的评论。

如果您正在寻找基于多个单词的接近度/相关性搜索结果进行排名的PHP算法,那么只需使用PHP即可快速简便地生成搜索结果:

其他布尔搜索方法的问题,如strpos()preg_match()strstr()stristr()

  1. 无法搜索多个单词
  2. 结果没有任何结果

基于向量空间模型tf-idf(术语频率 - 逆文档频率)的 PHP方法

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

如果我们想在字符串中搜索多个单词,核心问题是我们如何为每个单词分配权重?

如果我们可以根据字符串整体的代表性来对字符串中的术语进行加权,我们可以通过与查询最匹配的结果来排序结果。

这是向量空间模型的概念,与SQL全文搜索的工作方式相差不远:

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 from  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()

NOTA BENE

可选地在搜索单词之前消除冗余

  • 从而减小了索引大小并减少了存储需求

  • 减少磁盘I / O.

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

1.规范化

  • 将所有文本转换为小写

2.删除词汇

  • 消除文本中没有实际意义的词语(如'和','或','','for'等)

3.字典替换

  • 将词语替换为具有相同或相似含义的其他词语。 (例如:用'饥饿'代替'饥饿'和'饥饿'的例子)

  • 可以执行进一步的算法测量(滚雪球)以进一步将单词减少到其本质含义。

  • 用十六进制等值替换颜色名称

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

资源


如果你想避免“假”和“真理”问题,你可以使用substr_count:

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

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


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

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

如果要检查字符串是否包含多个特定单词,您可以执行以下操作:

echo FALSE === strpos($a,'are') ? 'false': '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
 }

您可以使用strstr函数:

$haystack = "I know programming";
$needle   = "know";
$flag = strstr($haystack, $needle);

if ($flag){

    echo "true";
}

不使用内置函数:

$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 ";
}

您可以使用正则表达式,与其他用户提到的strpos相比,它更适合单词匹配,对于诸如票价,关心,凝视等字符串,它也会返回true。这可以通过使用单词边界在正则表达式中简单地避免。

一个简单的匹配可能看起来像这样:

$a = 'How are you?';

if (preg_match('/\bare\b/',$a))
    echo 'true';

在性能方面,strpos的速度提高了大约三倍,并且考虑到,当我同时进行一百万次比较时,它需要1.5分钟的预匹配,并且需要花费0.5秒。


您需要使用相同/不相同的运算符,因为strpos可以返回0作为其索引值。 如果您喜欢三元运算符,请考虑使用以下内容(似乎有点倒退我会承认):

$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";
}

我有点印象,这里没有使用strposstrstr和类似函数提到多字节字符串函数的答案(2015-05-08)。

基本上,如果您在查找某些语言特有的字词时遇到问题 ,例如德语,法语,葡萄牙语,西班牙语等(例如: äéôçºñ ),您可能希望先于与mb_的函数。 因此,接受的答案将使用mb_strposmb_stripos (用于不区分大小写的匹配):

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

如果您无法保证所有数据都是100%UTF-8 ,则可能需要使用mb_函数。

一篇很好的文章,了解为什么绝对最低限度每个软件开发人员必须知道关于Unicode和字符集(没有借口!)Joel Spolsky


简易版

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

虽然这些答案中的大部分都会告诉您字符串中是否出现子字符串,但如果您要查找特定单词而不是字符串,则通常不是您想要的。

有什么不同? 子字符串可以出现在其他词语中:

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

减轻这种情况的一种方法是使用与单词边界相结合的正则表达式( \b ):

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

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

  • “你在想什么?”中的“是”?
  • “是谁”中的“大声笑”,那些是4?

如果你想要比这更准确的东西,你将不得不开始进行英语语法语法分析,这是一个非常大的蠕虫(并假设正确使用语法,无论如何,这并不总是给定)。


许多使用substr_count的答案检查结果是否>0 。 但由于if语句将false视为false ,因此可以避免直接检查和写入:

if (substr_count($a, 'are')) {

要检查是否存在,请添加! 运营商:

if (!substr_count($a, 'are')) {

这是一个小实用函数,在这种情况下很有用

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






string-matching