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



15 Answers

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

يمكن أن تبدو المطابقة البسيطة كالتالي:

$a = 'How are you?';

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

على جانب الأداء ، تكون سرعة strpos أسرع بثلاث مرات وتضع في الاعتبار ، عندما قمت بمقارنة مليون مرة في وقت واحد ، استغرق الأمر ما قبل المباراة 1.5 ثانية لإنهاء و strpos استغرق 0.5 ثانية.

php string substring contains string-matching

يعتبر:

$a = 'How are you?';

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

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




في حين أن معظم هذه الإجابات ستخبرك ما إذا كانت السلسلة الفرعية تظهر في السلسلة الخاصة بك ، فعادةً ما لا يكون هذا ما تريده إذا كنت تبحث عن كلمة معينة ، وليس سلسلة فرعية .

ماهو الفرق؟ يمكن أن تظهر الأجزاء الفرعية ضمن كلمات أخرى:

  • "هم" في بداية "المنطقة"
  • "هم" في نهاية "الأرنب"
  • "هي" في منتصف "فارس"

إحدى الطرق للتخفيف من ذلك هي استخدام تعبير عادي مقترن بحدود الكلمات ( \b ):

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

لا تحتوي هذه الطريقة على نفس الإيجابيات الخاطئة المذكورة أعلاه ، ولكنها تحتوي على بعض الحالات الحاسمة من تلقاء نفسها. تتطابق حدود Word مع الأحرف غير الكلمة ( \W ) ، والتي ستكون أي شيء غير az أو AZ أو 0-9 أو _ . هذا يعني أنه سيتم حساب الأرقام والشرطات السفلية كأحرف كلمات وستفشل سيناريوهات مثل هذا:

  • "هم" في "ماذا تفكر؟"
  • "هم" في "لول u dunno wut تلك are4؟"

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




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__ount:

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

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




الند لل SamGoody و تعليقات ليغو Stormtroopr.

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

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

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

طريقة PHP مبنية على نموذج Vector Space و Tf-idf (تردد تكرار تردد معاكس المدى):

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

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

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

هذه هي فكرة نموذج مساحة المتجه ، وليس بعيدًا عن كيفية عمل بحث النص الكامل في 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. القضاء على كلمة التوقف

  • استبعاد الكلمات من النص الذي لا يحمل أي معنى حقيقي (مثل "و" أو "أو" ، "" ، "إلى" ، إلخ.)

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

  • استبدل الكلمات بالآخرين التي لها معنى متطابق أو مشابه. (مثلا: استبدال حالات "الجوع" و "الجياع" مع "الجوع")

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

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

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

مصادر




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

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

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

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

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




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



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



النسخة قصيرة

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



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

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

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



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

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

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




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

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

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

$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 ، حيث تكون الكلمات عبارة عن سلاسل فرعية تتكون من أحرف الكلمة فقط ، ويتم فصلها بأحرف غير كلمة.

حرف "word" هو أي حرف أو رقم أو حرف تسطير أسفل السطر ، أي ، أي حرف يمكن أن يكون جزءًا من "كلمة" Perl. يتم التحكم في تعريف الحروف والأرقام بواسطة جداول الأحرف الخاصة بـ PCRE ، وقد يختلف ذلك إذا حدثت مطابقة خاصة باللغة (..)




يمكن التحقق من السلسلة باستخدام الوظيفة التالية:

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



Related