php - كيف يمكنني التحقق مما إذا كانت السلسلة تحتوي على كلمة معينة؟


يعتبر:

$a = 'How are you?';

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

افترض أن لدي الرمز أعلاه، ما هي الطريقة الصحيحة لكتابة البيان if ($a contains 'are') ؟




Answers


يمكنك استخدام الدالة strpos() التي تستخدم للعثور على حدوث سلسلة واحدة داخل آخر:

$a = 'How are you?';

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

لاحظ أن استخدام !== false متعمد. strpos() ترجع إما الإزاحة التي تبدأ سلسلة الإبرة في سلسلة كومة قش، أو false منطقية إذا لم يتم العثور على الإبرة. منذ 0 هو تعويض صالح و 0 هو "فالسي"، ونحن لا يمكن استخدام البنى أبسط مثل !strpos($a, 'are') .




يمكنك استخدام التعبيرات العادية. سيبدو شيء هكذا:

$a = 'How are you?';

if (preg_match('/are/',$a))
    echo 'true';

لا تخبرني انها سيئة فقط لأنك قد سمعت انها سيئة من قبل. قد يكون لديك أي حقائق لدعم ذلك على الرغم من؛)

على جانب الأداء، ستربوس هو حوالي ثلاث مرات أسرع و في الاعتبار، عندما فعلت مليون مقارنة في وقت واحد، استغرق بريغ المباراة 1.5 ثانية لإنهاء و ستربوس استغرق 0.5 ثانية. ما أحاول أن أقوله هو أنه يعمل بسرعة حقا في كلتا الحالتين. إذا لم يكن لديك 100000 زائر كل ثانية، يجب أن لا تهتم نفسك مع هذا النوع من الأشياء واتخاذ ما هو أكثر راحة، المنظمة البحرية الدولية.




استخدام وظيفة ستربوس :

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



هنا هو القليل من فائدة وظيفة مفيدة في مثل هذه الحالات

// 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 )، التي ستكون أي شيء غير az ، AZ ، 0-9 ، أو _ . وهذا يعني أن الأرقام والشرطات السفلية سيتم حسابها على أنها أحرف كلمة وسيناريوهات من هذا القبيل ستفشل:

  • و "هي" في "ما _are_ كنت تفكر؟"
  • و "هي" في "لول u دونو وت تلك are4؟"

إذا كنت تريد أي شيء أكثر دقة من هذا، سيكون عليك أن تبدأ في تحليل اللغة الإنجليزية بناء الجملة، وهذا هو كبير جدا يمكن من الديدان (ويفترض الاستخدام السليم من بناء الجملة، على أي حال، والتي ليست دائما معين).




لتحديد ما إذا كانت سلسلة تحتوي على سلسلة أخرى يمكنك استخدام دالة فب ستربوس () .

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 === علامة هي مقارنة لمعرفة ما إذا كان متغيرين / إكسبريسيونس / الثوابت متساوية ولها نفس النوع - أي كلاهما سلاسل أو كلاهما الأعداد الصحيحة.




استخدام stristr() strstr() أو stristr() إذا كان البحث يجب أن يكون غير حساس لحالة سيكون خيارا آخر.




انظر إلى 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.";
    }
?>



إذا كنت ترغب في تجنب "فالسي" و "الحقيقة" المشكلة، يمكنك استخدام subr_count:

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

انها أبطأ قليلا من ستربوس لكنه يتجنب مشاكل المقارنة.




استخدم مطابقة الحالة stripos() باستخدام stripos() :

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



خيار آخر هو استخدام الدالة سترستر () . شيء مثل:

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

يشير إلى ملاحظة: الدالة سترستر () حساسة لحالة الأحرف. للبحث عن حالة غير حساسة، استخدم الدالة ستريستر () .




الند إلى سامغودي وليغو ستورمتروبر التعليقات.

إذا كنت تبحث عن خوارزمية فب لترتيب نتائج البحث استنادا إلى القرب / صلة كلمات متعددة هنا يأتي وسيلة سريعة وسهلة لتوليد نتائج البحث مع فب فقط:

قضايا مع طرق البحث المنطقية الأخرى سوش كما strpos() ، preg_match() ، stristr() أو stristr()

  1. لا يمكن البحث عن كلمات متعددة
  2. النتائج غير مرتبة

طريقة فب على أساس نموذج المتجه الفضائي و تف-إدف (تردد الوثيقة العكسي للتردد العكسي):

يبدو صعبا ولكن من السهل بشكل مدهش.

إذا أردنا البحث عن كلمات متعددة في سلسلة، فإن المشكلة الأساسية هي كيفية تعيين وزن لكل واحد منها؟

إذا تمكنا من وزن العبارات في سلسلة استنادا إلى مدى تمثيلها للسلسلة ككل، يمكننا ترتيب نتائجنا حسب النتائج التي تتطابق بشكل أفضل مع طلب البحث.

هذه هي فكرة نموذج الفضاء المتجه، وليس بعيدا عن كيفية عمل بحث النص الكامل سكل:

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() ، stristr() أو stristr() .

نوتا بين

اختياريا القضاء على التكرار قبل البحث في الكلمات

  • مما يقلل من حجم المؤشر ويؤدي إلى أقل متطلبات التخزين

  • أقل القرص I / O

  • أسرع الفهرسة وبالتالي أسرع البحث.

1. التطبيع

  • تحويل كل النص إلى حالة أقل

2. وقف كلمة القضاء

  • القضاء على الكلمات من النص الذي لا يحمل معنى حقيقيا (مثل 'و'، 'أو'، 'و'، 'ل'، وما إلى ذلك)

3. استبدال القاموس

  • يستعاض عن عبارة "مع الآخرين" التي لها معنى مماثل أو مشابه. (مثال: استبدال حاالت "الجوع" و "الجائع" ب "الجوع"

  • ويمكن إجراء المزيد من التدابير الخوارزمية (كرة الثلج) لمواصلة تقليل الكلمات إلى معناها الأساسي.

  • استبدال أسماء الألوان مع مكافئاتها الست عشرية

  • الحد من القيم الرقمية عن طريق الحد من الدقة هي طرق أخرى لتطبيع النص.

مصادر




أنا أعجب قليلا أن أيا من الإجابات هنا أن تستخدم strpos ، strpos وظائف مماثلة المذكورة مولتيبيت سلسلة وظائف حتى الآن (2015-05-08).

في الأساس، إذا كنت تواجه مشكلة في العثور على الكلمات ذات الأحرف الخاصة ببعض اللغات ، مثل الألمانية والفرنسية والبرتغالية والإسبانية وغيرها (على سبيل المثال: ä ، é ، ô ، ç ، º ، ñ )، قد ترغب في أن تسبق الوظائف مع mb_ . لذلك، فإن الإجابة المقبولة ستستخدم mb_strpos أو mb_stripos (لمطابقة الأحرف غير الحساسة) بدلا من ذلك:

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

إذا لم تتمكن من ضمان أن جميع البيانات الخاصة بك 100٪ في أوتف-8 ، قد ترغب في استخدام وظائف mb_ .

مقال جيد لفهم لماذا هو المطلق الحد الأدنى كل مطور البرامج على الاطلاق، يجب أن نعرف إيجابيا عن يونيكود ومجموعات الأحرف (لا أعذار!) من قبل جول سبولسكي .




وظيفة أدناه أيضا يعمل ولا يعتمد على أي وظيفة أخرى. فإنه يستخدم فقط فب التلاعب سلسلة الأصلي. شخصيا، أنا لا أوصي هذا، ولكن يمكنك أن ترى كيف يعمل:

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



if (preg_match('are', $a)) {
   echo 'true';
}



كان لي بعض المتاعب مع هذا، وأخيرا اخترت لخلق حل بلدي. دون استخدام محرك التعبير العادي :

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 .




يمكنك استخدام الدالة 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 ";
}



يجب عليك استخدام شكل حالة حساس، حتى إذا كانت القيمة المدخلة في small أو caps فإنه لن يهم.

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

هنا يجد ستريبوس إبرة في هيستاك دون النظر في حالة (صغيرة / قبعات).

عينة فكود مع الإخراج




النسخة قصيرة اليد

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



من أجل العثور على 'كلمة'، بدلا من حدوث سلسلة من الرسائل التي يمكن أن تكون في الواقع جزءا من كلمة أخرى، فإن ما يلي سيكون حلا جيدا.

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

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



وهناك خيار آخر للعثور على حدوث كلمة من سلسلة باستخدام سترستر () و ستريستر () مثل ما يلي:

<?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- ستريستر ()

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

2- ستربوس ()

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



لا تستخدم preg_match() إذا كنت ترغب فقط في التحقق من وجود سلسلة واحدة في سلسلة أخرى. استخدم strpos() أو strpos() بدلا من ذلك لأنها ستكون أسرع. ( http://in2.php.net/preg_match )

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



في فب، فإن أفضل طريقة للتحقق مما إذا كانت سلسلة تحتوي على سلسلة فرعية معينة، هي استخدام وظيفة مساعد بسيطة مثل هذا:

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

تفسير:

  • strpos يجد موقف أول حدوث سلسلة فرعية حساسة لحالة الأحرف في سلسلة.
  • 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)



تحتاج إلى استخدام مشغلي متطابقة / غير متطابقة لأن ستربوس يمكن أن ترجع 0 كما انها قيمة الفهرس. إذا كنت ترغب في مشغلي الثلاثي، والنظر في استخدام ما يلي (يبدو قليلا إلى الوراء وأنا أعترف):

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



إذا كنت تريد التحقق مما إذا كانت السلسلة تحتوي على عدة كلمات محددة، فيمكنك إجراء ما يلي:

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

وهذا مفيد لتجنب الرسائل غير المرغوب فيها عند إرسال رسائل البريد الإلكتروني على سبيل المثال.




وظيفة ستربوس يعمل بشكل جيد، ولكن إذا كنت تريد أن تفعل case-insensitive التحقق من كلمة في فقرة ثم يمكنك الاستفادة من وظيفة stripos PHP .

فمثلا،

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

العثور على موقف أول حدوث سلسلة فرعية غير حساسة لحالة الأحرف في سلسلة.

إذا كانت الكلمة غير موجودة في السلسلة ثم سيعود كاذبة وإلا فإنه سيعود موقف الكلمة.




تحقق مما إذا كانت السلسلة تحتوي على كلمات محددة؟

وهذا يعني أن السلسلة يجب حلها إلى كلمات (انظر الملاحظة أدناه).

هناك طريقة واحدة للقيام بذلك وتحديد الفواصل باستخدام preg_split ( دوك ):

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

ملاحظة: نحن هنا لا يعني كلمة لكل تسلسل من الرموز.

تعريف عملي للكلمة هو بمعنى محرك التعبير العادي يكر، حيث الكلمات هي سلاسل فرعية تتكون من أحرف كلمة فقط، مفصولة بأحرف غير كلمة.

حرف "كلمة" هو أي حرف أو رقم أو حرف شرطة سفلية، أي أي حرف يمكن أن يكون جزءا من بيرل "كلمة". يتم التحكم في تعريف الحروف والأرقام من خلال جداول حرف يكر، ويمكن أن تختلف إذا كانت مطابقة محددة للموقع تجري (..)