Вопрос: Как проверить, содержит ли строка определенное слово?


Рассматривать:

$a = 'How are you?';

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

Предположим, что у меня есть код выше, какой правильный способ написать оператор if ($a contains 'are')?


2668


источник


Ответы:


Вы можете использовать strpos()функция, которая используется для поиска вхождения одной строки в другую:

$a = 'How are you?';

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

Обратите внимание, что использование !== falseявляется преднамеренным; strpos()возвращает либо смещение, при котором начинается строка иглы в строке стога сена, или логическое значение falseесли игла не найдена. Поскольку 0 является допустимым смещением, а 0 является «ложным», мы не можем использовать более простые конструкции, такие как !strpos($a, 'are'),


5323



Вы можете использовать регулярные выражения, лучше для сопоставления слов по сравнению с strpos, как упомянуто другими пользователями, он также вернет true для строк, таких как тариф, уход, stare и т. Д. Этого можно просто избежать в регулярном выражении, используя границы слов.

Простой матч для них может выглядеть примерно так:

$a = 'How are you?';

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

С точки зрения производительности, strpos примерно в три раза быстрее и имеет в виду, когда я делал один миллион сравнений сразу, для завершения игры потребовалось 1,5 секунды, а для strpos - 0,5 секунды.


441



Вот небольшая полезная функция, которая полезна в таких ситуациях

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

187



Хотя большинство этих ответов скажут вам, есть ли подстрока в вашей строке, это обычно не то, что вы хотите, если ищете конкретную слово , а не подстрока ,

Какая разница? Подстроки могут появляться иными словами:

  • «Находятся» в начале «области»,
  • «Есть» в конце «заяц»,
  • «Находятся» в середине «тарифов»,

Одним из способов смягчения этого было бы использование регулярного выражения в сочетании с границы слов ( \b):

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

Этот метод не имеет тех же ложных срабатываний, которые были отмечены выше, но у него есть некоторые краевые случаи. Границы слов соответствуют символам, отличным от слов ( \W), которые будут тем, что не является a-z, A-Z, 0-9, или _, Это означает, что цифры и символы подчеркивания будут считаться символами слов, и сценарии, подобные этому, не будут выполнены:

  • «Есть» в «Что ты думаешь?»
  • «Есть» в «lol u dunno wut that are4?»

Если вам нужно что-то более точное, вам придется начинать синтаксический синтаксис на английском языке, и это довольно большая возможность червей (и предполагает правильное использование синтаксиса, так или иначе, что не всегда является данным).


112



Чтобы определить, содержит ли строка другую строку, вы можете использовать функцию 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, если вы выполните ==сравните, что не сработает, вам нужно будет сделать ===

==знак - это сравнение и проверяет, имеет ли переменная / выражение / константа влево то же значение, что и переменная / выражение / постоянная справа.

===знак - это сравнение, чтобы определить, равны ли две переменные / выражения / константы ANDимеют один и тот же тип, т. е. оба являются строками или оба являются целыми числами.


89



Using strstr() or stristr() if your search should be case insensitive would be another option.


55



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

54



If you want to avoid the "falsey" and "truthy" problem, you can use substr_count:

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

It's a bit slower than strpos but it avoids the comparison problems.


36



Make use of case-insensitve matching using stripos():

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

36



Peer to SamGoody and Lego Stormtroopr comments.

If you are looking for a PHP algorithm to rank search results based on proximity/relevance of multiple words here comes a quick and easy way of generating search results with PHP only:

Issues with the other boolean search methods such as strpos(), preg_match(), strstr() or stristr()

  1. can't search for multiple words
  2. results are unranked

PHP method based on Vector Space Model and tf-idf (term frequency–inverse document frequency):

It sounds difficult but is surprisingly easy.

If we want to search for multiple words in a string the core problem is how we assign a weight to each one of them?

If we could weight the terms in a string based on how representative they are of the string as a whole, we could order our results by the ones that best match the query.

This is the idea of the vector space model, not far from how SQL full-text search works:

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

CASE 1

$query = 'are';

$corpus = array(
    1 => 'How are you?',
);

$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
    print_r($match_results);
echo '</pre>';

RESULT

Array
(
    [1] => 0.52832083357372
)

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

RESULTS

Array
(
    [1] => 0.54248125036058
    [3] => 0.21699250014423
)

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

RESULTS

Array
(
    [3] => 0.6813781191217
    [1] => 0.54248125036058
)

There are plenty of improvements to be made but the model provides a way of getting good results from natural queries, which don't have boolean operators such as strpos(), preg_match(), strstr() or stristr().

NOTA BENE

Optionally eliminating redundancy prior to search the words

  • thereby reducing index size and resulting in less storage requirement

  • less disk I/O

  • faster indexing and a consequently faster search.

1. Normalisation

  • Convert all text to lower case

2. Stopword elimination

  • Eliminate words from the text which carry no real meaning (like 'and', 'or', 'the', 'for', etc.)

3. Dictionary substitution

  • Replace words with others which have an identical or similar meaning. (ex:replace instances of 'hungrily' and 'hungry' with 'hunger')

  • Further algorithmic measures (snowball) may be performed to further reduce words to their essential meaning.

  • The replacement of colour names with their hexadecimal equivalents

  • The reduction of numeric values by reducing precision are other ways of normalising the text.

RESOURCES


32