strpos用法 - php substring




如何檢查字符串是否包含特定單詞? (20)

檢查字符串是否包含特定單詞?

這意味著必須將字符串解析為單詞(請參閱下面的註釋)。

執行此操作和指定分隔符的一種方法是使用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的字符表控制,如果發生特定於語言環境的匹配,則可能會有所不同(..)

考慮:

$a = 'How are you?';

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

假設我有上面的代碼, if ($a contains 'are') ,編寫語句的正確方法if ($a contains 'are')什麼?


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,否則它將返回該單詞的位置。


也許你可以使用這樣的東西:

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

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

以下功能也有效,不依賴於任何其他功能; 它僅使用本機PHP字符串操作。 就個人而言,我不推薦這個,但你可以看到它是如何工作的:

<?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;
  }
}

測試:

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 

使用strstr()stristr()從字符串中查找單詞出現的另一個選項如下所示:

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

另一種選擇是使用strstr()函數。 就像是:

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

注意:strstr()函數區分大小寫。 對於不區分大小寫的搜索,請使用stristr()函數。


同意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.字典替換

  • 將詞語替換為具有相同或相似含義的其他詞語。 (例如:用'飢餓'代替'飢餓'和'飢餓'的例子)

  • 可以執行進一步的算法測量(滾雪球)以進一步將單詞減少到其本質含義。

  • 用十六進制等值替換顏色名稱

  • 通過降低精度來減少數值是標準化文本的其他方法。

資源


在PHP中,驗證字符串是否包含某個子字符串的最佳方法是使用這樣的簡單輔助函數:

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

說明:

  • strpos()查找字符串中第一次出現區分大小寫的子字符串的位置。
  • stripos()stripos()查找第一次出現不區分大小寫的子字符串的位置。
  • myFunction($haystack, $needle) === FALSE ? FALSE : TRUE myFunction($haystack, $needle) === FALSE ? FALSE : TRUE確保myFunction總是返回一個布爾值,並在子字符串的索引為0時修復意外行為。
  • $caseSensitive ? A : B $caseSensitive ? A : B選擇strpos()stripos()來完成工作,具體取決於$caseSensitive的值。

輸出:

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)

如果您只想檢查另一個字符串中是否包含一個字符串,請不要使用preg_match() 。 使用strpos()strstr()代替它們會更快。 ( http://in2.php.net/preg_match

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

如果您的搜索不區分大小寫,則使用strstr()stristr()將是另一種選擇。


它可以通過三種不同的方式完成:

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

您可以使用strpos()函數來查找另一個字符串中出現的一個字符串:

$a = 'How are you?';

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

注意使用!== false是故意的; strpos()返回針字符串在haystack字符串中開始的偏移量,如果未找到針,則返回布爾值false 。 由於0是有效偏移量而0是“假”,我們不能使用更簡單的結構,如!strpos($a, 'are')


您可以使用正則表達式,與其他用戶提到的strpos相比,它更適合單詞匹配,對於諸如票價,關心,凝視等字符串,它也會返回true。這可以通過使用單詞邊界在正則表達式中簡單地避免。

一個簡單的匹配可能看起來像這樣:

$a = 'How are you?';

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

在性能方面,strpos的速度提高了大約三倍,並且考慮到,當我同時進行一百萬次比較時,它需要1.5分鐘的預匹配,並且需要花費0.5秒。


您應該使用大小寫不敏感的格式,因此如果輸入的值smallcaps則無關緊要。

<?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樣品


我有點印象,這裡沒有使用strposstrstr和類似函數提到多字節字符串函數的答案(2015-05-08)。

基本上,如果您在查找某些語言特有的字詞時遇到問題 ,例如德語,法語,葡萄牙語,西班牙語等(例如: äéôçºñ ),您可能希望先於與mb_的函數。 因此,接受的答案將使用mb_strposmb_stripos (用於不區分大小寫的匹配):

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

如果您無法保證所有數據都是100%UTF-8 ,則可能需要使用mb_函數。

一篇很好的文章,了解為什麼絕對最低限度每個軟件開發人員必須知道關於Unicode和字符集(沒有藉口!)Joel Spolsky


我遇到了一些麻煩,最後我選擇創建自己的解決方案。 不使用正則表達式引擎:

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

您可能會注意到,之前的解決方案不是將該詞用作另一個詞的前綴的答案。 為了使用你的例子:

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

對於上面的示例, $a$b包含$c ,但您可能希望您的函數告訴您只有$a包含$c


簡易版

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

要確定字符串是否包含另一個字符串,可以使用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";
}

?>

警告:

如果您正在搜索的針頭位於乾草堆的開頭,它將返回位置0,如果您執行==比較不起作用,則需要執行===

A ==符號是一個比較,並測試左側的變量/表達式/常量是否與右側的變量/表達式/常量具有相同的值。

A ===符號是比較以查看兩個變量/表達式/常量是否相等且具有相同的類型 - 即兩者都是字符串或兩者都是整數。


這是一個小實用函數,在這種情況下很有用

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

雖然這些答案中的大部分都會告訴您字符串中是否出現子字符串,但如果您要查找特定單詞而不是字符串,則通常不是您想要的。

有什麼不同? 子字符串可以出現在其他詞語中:

  • “區域”開頭的“是”
  • “野兔”結束時的“是”
  • 在“票價”中間的“是”

減輕這種情況的一種方法是使用與單詞邊界相結合的正則表達式( \b ):

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

這種方法沒有上面提到的相同的誤報,但它確實有一些自己的邊緣情況。 字邊界匹配非單詞字符( \W ),這些字符將是非azAZ0-9_ 。 這意味著數字和下劃線將被計為單詞字符,這樣的場景將失敗:

  • “你在想什麼?”中的“是”?
  • “是誰”中的“大聲笑”,那些是4?

如果你想要比這更準確的東西,你將不得不開始進行英語語法語法分析,這是一個非常大的蠕蟲(並假設正確使用語法,無論如何,這並不總是給定)。







string-matching