php - مقاطع - معرفة جودة الفيديو




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

يعتبر:

$a = 'How are you?';

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

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


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

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

طريقة واحدة للقيام بذلك وتحديد الفواصل تستخدم 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 ، وقد يختلف ذلك إذا حدثت مطابقة خاصة باللغة (..)


أنا معجبة بعض الشيء أن أيا من الإجابات هنا التي تستخدم 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 .


إذا كنت تريد تجنب مشكلة "falsey" و "truthy" ، فيمكنك استخدام substr__ount:

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

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


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


الكثير من الإجابات التي تستخدم التحقق من substr_count إذا كانت النتيجة >0 . ولكن نظرًا لأن العبارة if تعتبر صفرًا كقيمة false ، فيمكنك تجنب هذا الاختيار والكتابة مباشرة:

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

للتحقق مما إذا لم يكن موجودًا ، أضف ! المشغل أو العامل:

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

الند لل 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 يمكن أن ترجع 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";
}

تعمل الوظيفة أدناه أيضًا ولا تعتمد على أي وظيفة أخرى ؛ ويستخدم فقط تلاعب سلسلة 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 

ربما يمكنك استخدام شيء كهذا:

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

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

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

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($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';
}

لتحديد ما إذا كانت سلسلة تحتوي على سلسلة أخرى يمكنك استخدام strpos() الدالة 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 ، إذا قمت بعمل مقارنة == التي لن تنجح ، فستحتاج إلى إجراء ===

علامة == هي مقارنة وتختبر ما إذا كان المتغير / التعبير / الثابت إلى اليسار له نفس قيمة المتغير / التعبير / الثابت إلى اليمين.

علامة === هي مقارنة لمعرفة ما إذا كان هناك متغيرين / expresions / ثوابت متساوية ولهما نفس النوع - أي أن كلاهما عبارة عن سلاسل أو كلاهما صحيح.


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

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

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

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() و 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
 }

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

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

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

$a = 'How are you?';

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

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


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

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

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

فمثلا،

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

ابحث عن موضع التواجد الأول لسلسلة فرعية غير حساسة لحالة الأحرف في سلسلة.

إذا لم تكن الكلمة موجودة في السلسلة ، فستعرضها كاذبة وإلا فسوف تُرجع موضع الكلمة.





string-matching