Jak sprawdzić, czy ciąg zawiera określone słowo?


2661

Rozważać:

$a = 'How are you?';

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

Załóżmy, że mam powyższy kod. Jaki jest prawidłowy sposób napisania instrukcji if ($a contains 'are')?

Odpowiedzi:


6888

Możesz użyć strpos()funkcji, która służy do znalezienia wystąpienia jednego ciągu wewnątrz drugiego:

$a = 'How are you?';

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

Zauważ, że użycie !== falsejest celowe (ani != falsenie === truezwróci pożądanego wyniku); strpos()zwraca albo przesunięcie, od którego zaczyna się łańcuch igły w łańcuchu stogu siana, albo wartość logiczną, falsejeśli igły nie znaleziono. Ponieważ 0 jest prawidłowym przesunięciem, a 0 to „falsey”, nie możemy używać takich prostszych konstrukcji jak !strpos($a, 'are').


261
Bardzo późno na imprezę, ale bądź ostrożny z tym. To również zwróci prawdę dla ciągu „Czy cię to obchodzi?”
DTest

167
@DTest - no tak, oczywiście, że zwróci prawdę, ponieważ ciąg zawiera „są”. Jeśli szukasz właśnie słowa ARE, musisz wykonać więcej czynności kontrolnych, na przykład sprawdzić, czy przed
literą

40
Bardzo dobre komentarze powyżej! Nigdy nie używam! = Lub ==, w końcu! == i === to najlepsza opcja (moim zdaniem) pod każdym względem (szybkość, dokładność itp.).
Melsi

10
@jsherk Dlaczego więc nie wyrażenia regularne? Coś w stylu „są”.
Giulio Muscarello,

21
Staram się unikać tego problemu, zawsze strpos($a, 'are') > -1testując prawdziwość. Z perspektywy debugowania stwierdzam, że mój mózg marnuje mniej cykli zegara, określając, czy linia jest poprawnie zapisana, gdy nie muszę liczyć ciągłych znaków równości.
equazcion

607

Możesz użyć wyrażeń regularnych, lepiej pasujących do słów, niż strposwspomniane przez innych użytkowników, zwróci również wartość dla ciągów takich jak taryfa, opieka, gap itp. Można tego po prostu uniknąć w wyrażeniach regularnych, używając granic słów.

Proste dopasowanie dla może wyglądać mniej więcej tak:

$a = 'How are you?';

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

Po stronie wydajności strposjest około trzy razy szybsza i pamiętaj, że kiedy zrobiłem milion porównań na raz, zajęło to preg_match1,5 sekundy, a strposzajęło to 0,5 sekundy.

Edycja: Aby przeszukać dowolną część ciągu, nie tylko słowo po słowie, zaleciłbym użycie wyrażenia regularnego, takiego jak

$a = 'How are you?';
$search = 'are y';
if(preg_match("/{$search}/i", $a)) {
    echo 'true';
}

Na ikońcu wyrażenia regularnego zmieniane jest wyrażenie regularne, w którym nie jest rozróżniana wielkość liter, jeśli nie chcesz tego, możesz je pominąć.

Teraz może to być dość problematyczne w niektórych przypadkach, ponieważ ciąg $ $ nie jest w żaden sposób odkażany, to znaczy, w niektórych przypadkach może nie przejść testu, ponieważ $searchużytkownik może dodać ciąg znaków, który może zachowywać się jak jakieś inne wyrażenie regularne ...

Ponadto, oto świetne narzędzie do testowania i przeglądania wyjaśnień różnych wyrażeń regularnych Regex101

Aby połączyć oba zestawy funkcji w jedną funkcję wielofunkcyjną (w tym z wybieraną rozróżnianiem wielkości liter), możesz użyć czegoś takiego:

function FindString($needle,$haystack,$i,$word)
{   // $i should be "" or "i" for case insensitive
    if (strtoupper($word)=="W")
    {   // if $word is "W" then word search instead of string in string search.
        if (preg_match("/\b{$needle}\b/{$i}", $haystack)) 
        {
            return true;
        }
    }
    else
    {
        if(preg_match("/{$needle}/{$i}", $haystack)) 
        {
            return true;
        }
    }
    return false;
    // Put quotes around true and false above to return them as strings instead of as bools/ints.
}

9
@ Alexander.Plutov po drugie, dajesz mi -1, a nie pytanie? cmon, znalezienie odpowiedzi w google.com/…
Breezer

64
+1 To okropny sposób wyszukiwania prostego ciągu, ale wielu odwiedzających SO szuka jakiegokolwiek sposobu na wyszukanie własnych podciągów i pomocne jest, aby sugestia została przywołana. Nawet PO mógł się uprościć - daj mu znać o swoich alternatywach.
SamGoody,

72
Technicznie pytanie dotyczy tego, jak znaleźć słowa nie będące podciągiem. To faktycznie pomogło mi, ponieważ mogę używać tego z granicami wyrażeń regularnych. Alternatywy są zawsze przydatne.

15
+1 za odpowiedź i -1 do komentarza @ plutov.by, ponieważ strpos jest tylko pojedynczym sprawdzaniem, podczas gdy wyrażenie regularne możesz sprawdzić wiele słów w tym samym czasie np: preg_match (/ are | you | not /)
albanx

4
Wyrażenia regularne powinny być metodą ostateczną. Należy odradzać ich stosowanie w trywialnych zadaniach. Nalegam na to od szczytu wielu lat kopania złego kodu.
yentsun

256

Oto mała funkcja użyteczna w takich sytuacjach

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

74
@RobinvanBaalen W rzeczywistości może poprawić czytelność kodu. Ponadto, głosy negatywne powinny dotyczyć (bardzo) złych odpowiedzi, a nie odpowiedzi „neutralnych”.
Xaqq,

37
Funkcje @RobinvanBaalen są z definicji prawie czytelne (przekazują ideę tego, co robisz). Porównaj, co jest bardziej czytelne: if ($email->contains("@") && $email->endsWith(".com)) { ...lubif (strpos($email, "@") !== false && substr($email, -strlen(".com")) == ".com") { ...
Brandin,

3
@RobinvanBaalen w regulaminie końcowym mają być złamane. W przeciwnym razie ludzie nie wymyślą nowatorskich sposobów robienia rzeczy :). Dodatkowo muszę przyznać, że mam problem z otuleniem umysłu wokół rzeczy takich jak na martinfowler.com. Zgadnij, co należy zrobić, to wypróbować rzeczy samodzielnie i dowiedzieć się, jakie podejścia są najbardziej wygodne.
James P.

5
Kolejna opinia: Posiadanie funkcji narzędzia, którą można łatwo owinąć, może pomóc w debugowaniu. To także pobudza wołanie o dobre optymalizatory, które eliminują takie koszty ogólne w usługach produkcyjnych. Więc wszystkie opinie mają ważne punkty. ;)
Tino

18
Oczywiście jest to przydatne. Powinieneś zachęcić to. Co się stanie, jeśli w PHP 100 istnieje nowy i szybszy sposób wyszukiwania lokalizacji ciągów? Czy chcesz zmienić wszystkie miejsca, w których nazywasz się strpos? A może chcesz zmienić tylko zawartość w ramach funkcji?
Cosmin,

143

Podczas gdy większość tych odpowiedzi powie ci, czy w twoim ciągu pojawia się podłańcuch, zazwyczaj nie jest to to, czego szukasz, jeśli szukasz określonego słowa , a nie podłańcuch .

Co za różnica? Podciągi mogą pojawiać się w innych słowach:

  • „Są” na początku „obszaru”
  • „Są” na końcu „zająca”
  • „Są” w środku „taryf”

Jednym ze sposobów złagodzenia tego byłoby użycie wyrażenia regularnego połączonego z granicami słów ( \b):

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

Ta metoda nie ma tych samych fałszywych wyników pozytywnych, co wspomniano powyżej, ale ma kilka własnych przypadków skrajnych. Granice słów pasuje na znaki nie-słowa ( \W), które będzie niczego, co jest nie a-z, A-Z, 0-9, lub _. Oznacza to, że cyfry i podkreślenia będą liczone jako znaki słowne i takie scenariusze zakończą się niepowodzeniem:

  • „Są” w „Co myślisz?”
  • The are are in lol u dunno wut one are4?

Jeśli chcesz czegoś dokładniejszego niż to, musisz zacząć analizowanie składni w języku angielskim, a to całkiem spora paczka robaków (przy założeniu właściwego użycia składni, co nie zawsze jest dane).


24
taka powinna być odpowiedź kanoniczna. Ponieważ szukamy słów, a nie podłańcuchów , wyrażenie regularne jest odpowiednie. Dodam również, że \bpasuje do dwóch rzeczy, które \Wnie pasują , co sprawia, że ​​świetnie nadaje się do wyszukiwania słów w ciągu: ^$
Pasuje do

powinna to być poprawna odpowiedź. Pozostałe odpowiedzi będą zawierać „są” w ciągach takich jak „czy cię to obchodzi”. Jak wspomniała @Dtest
Robert Sinclair

@RobertSinclair Czy to takie złe? Gdybyś zapytał mnie, czy ciąg „czy to cię obchodzi” zawiera słowo „są”, powiedziałbym „tak”. Słowo „are” jest wyraźnie podciągiem tego ciągu. To osobne pytanie od „” „Jest” to „jedno ze słów w ciągu„ czy cię to obchodzi ”„ ”.
Paul

@Paulpro Eventhough OP nie określił, że $ a jest frazą, jestem prawie pewien, że została implikowana. Więc jego pytanie brzmiało, jak wykryć Słowo w wyrażeniu. Nie, jeśli Słowo zawiera w sobie Słowo, które, jak sądzę, byłoby nieistotne częściej niż nie.
Robert Sinclair,

@Jimbo to działa, po prostu brakuje Ci pliku
MetalWeirdo

125

Aby ustalić, czy łańcuch zawiera inny ciąg, możesz użyć funkcji 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";
}

?>

UWAGA:

Jeśli igła, której szukasz, znajduje się na początku stogu siana, zwróci pozycję 0, jeśli wykonasz ==porównanie, które nie zadziała, musisz zrobić===

==Znak jest porównanie i sprawdza czy zmienna / wyrażenie / stała na lewo ma taką samą wartość jak zmiennej / stałej ekspresji / w prawo.

===Znak to porównanie, aby zobaczyć, czy dwie zmienne / expresions / stałe są równe ANDmają ten sam typ - czyli oba ciągi lub oba są liczbami całkowitymi.


67

Spójrz nastrpos() :

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

62

Innym rozwiązaniem byłoby użycie strstr()lub stristr()jeśli wyszukiwanie nie uwzględnia wielkości liter.


9
Uwaga na stronie php.net/manual/en/function.strstr.php : Uwaga: Jeśli chcesz tylko ustalić, czy konkretna igła występuje w stogu siana, użyj zamiast tego szybszej i mniej wymagającej pamięci funkcji strpos ().
Jo Smo

@tastro Czy są w tym jakieś renomowane testy?
Wayne Whitty,

To może być wolniejsze, ale IMHO strstr($a, 'are')jest znacznie bardziej eleganckie niż brzydkie strpos($a, 'are') !== false. PHP naprawdę potrzebuje str_contains()funkcji.
Paul Spiegel,



45

Zobacz komentarze SamGoody i Lego Stormtroopr.

Jeśli szukasz algorytmu PHP do pozycjonowania wyników wyszukiwania na podstawie bliskości / trafności wielu słów, oto szybki i łatwy sposób generowania wyników wyszukiwania tylko przy pomocy PHP:

Problemy z innych metod, takich jak boolean wyszukiwania strpos(), preg_match(), strstr()lubstristr()

  1. nie można wyszukać wielu słów
  2. wyniki są nierankingowane

Metoda PHP oparta na Vector Space Model i tf-idf (termin częstotliwość – odwrotna częstotliwość dokumentów):

Brzmi to trudne, ale zaskakująco łatwe.

Jeśli chcemy wyszukać wiele słów w ciągu, głównym problemem jest to, jak przypisujemy wagę każdemu z nich?

Gdybyśmy mogli zważyć parametry w ciągu znaków w oparciu o ich reprezentatywność dla ciągu jako całości, moglibyśmy uporządkować nasze wyniki według tych, które najlepiej pasują do zapytania.

Oto idea modelu przestrzeni wektorowej, niedaleko działania wyszukiwania pełnotekstowego 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;
}

PRZYPADEK 1

$query = 'are';

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

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

WYNIK

Array
(
    [1] => 0.52832083357372
)

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

WYNIKI

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

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

WYNIKI

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

Istnieje wiele ulepszeń należy dokonać ale model jest sposobem na uzyskanie dobrych wyników z naturalnych zapytań, które nie mają operatorów logicznych takich jak strpos(), preg_match(), strstr()lub stristr().

NOTA BENE

Opcjonalnie eliminując nadmiarowość przed wyszukiwaniem słów

  • zmniejszając w ten sposób rozmiar indeksu i powodując mniejsze zapotrzebowanie na miejsce

  • mniej We / Wy dysku

  • szybsze indeksowanie i w konsekwencji szybsze wyszukiwanie.

1. Normalizacja

  • Konwertuj cały tekst na małe litery

2. Eliminacja słów kluczowych

  • Wyeliminuj słowa z tekstu, które nie mają żadnego znaczenia (jak „i”, „lub”, „the”, „for” itp.)

3. Podstawienie słownika

  • Zamień słowa na inne, które mają identyczne lub podobne znaczenie. (np. zamień przypadki „głodnego” i „głodnego” na „głód”)

  • Można zastosować dalsze miary algorytmiczne (śnieżka) w celu dalszego zredukowania słów do ich podstawowego znaczenia.

  • Zastąpienie nazw kolorów ich ekwiwalentami szesnastkowymi

  • Zmniejszenie wartości liczbowych przez zmniejszenie precyzji to inne sposoby normalizacji tekstu.

ZASOBY


40

Jeśli chcesz uniknąć problemów z „falseyem” i „prawdą”, możesz użyć substr_count:

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

Jest nieco wolniejszy niż strpos, ale pozwala uniknąć problemów z porównaniem.


Zwraca false„jesteś pewien?” ponieważ pozycja na strposto0
Hafenkranich

30

Inną opcją jest użycie funkcji strstr () . Coś jak:

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

Uwaga: w funkcji strstr () rozróżniana jest wielkość liter. Aby wyszukiwać bez rozróżniania wielkości liter, użyj funkcji stristr () .


1
Funkcja strstr () zwraca FALSE, jeśli igła nie została znaleziona. Więc strlen nie jest konieczny.
Ayesh K

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

3
Otrzymuję następujące ostrzeżenie:WARNING preg_match(): Delimiter must not be alphanumeric or backslash
Pathros,

27

Jestem pod wrażeniem, że żadna z odpowiedzi, które tu zastosowano strpos, strstri podobne funkcje nie wspomniały jeszcze o ciągach znaków wielobajtowych (2015-05-08).

Zasadniczo, jeśli masz problemy ze znalezieniem słów ze znakami specyficznymi dla niektórych języków , takich jak niemiecki, francuski, portugalski, hiszpański itp. (Np .: ä , é , ô , ç , º , ñ ), możesz chcieć poprzedzić funkcje z mb_. Dlatego zaakceptowana odpowiedź użyłaby mb_strposlub mb_stripos(dla dopasowania bez rozróżniania wielkości liter):

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

Jeśli nie możesz zagwarantować, że wszystkie twoje dane są w 100% w UTF-8 , możesz skorzystać z mb_funkcji.

Dobry artykuł, aby zrozumieć, dlaczego jest absolutne minimum Każdy Programista absolutnie, pozytywnie musi wiedzieć O Unicode i zestawy znaków (bez wymówek!) Przez Joel Spolsky .


25

W PHP najlepszym sposobem sprawdzenia, czy łańcuch zawiera określony podciąg, jest użycie prostej funkcji pomocniczej, takiej jak ta:

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

Wyjaśnienie:

  • strpos znajduje pozycję pierwszego wystąpienia ciągu znaków z rozróżnianiem wielkości liter.
  • stripos znajduje pozycję pierwszego wystąpienia podciągu bez rozróżniania wielkości liter w ciągu.
  • myFunction($haystack, $needle) === FALSE ? FALSE : TRUEzapewnia, że myFunctionzawsze zwraca wartość logiczną i naprawia nieoczekiwane zachowanie, gdy indeks podciągu wynosi 0.
  • $caseSensitive ? A : Bwybiera albo strposalbo striposdo wykonania pracy, w zależności od wartości $caseSensitive.

Wynik:

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)

22

Poniższa funkcja działa również i nie zależy od żadnej innej funkcji; używa tylko natywnej manipulacji ciągiem PHP. Osobiście nie polecam tego, ale możesz zobaczyć, jak to działa:

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

Test:

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 

13
Czy mógłbyś mi powiedzieć, dlaczego na świecie użyłbyś takiej funkcji, skoro strpos jest całkowicie wykonalnym rozwiązaniem? ...
SG3S

3
@ sg3s: masz całkowitą rację, jednak strpos również oparte na czymś takim, również nie opublikowałem go dla przedstawiciela tylko za podzielenie się odrobiną wiedzy
Jason OOO

ostatni zmienna_dump jest fałszywa
Słoneczny

1
@Sunny: to była literówka: var_dump (is_str_contain („mystringss”, „strings”)); // true
Jason OOO

22

Możesz użyć strstrfunkcji:

$haystack = "I know programming";
$needle   = "know";
$flag = strstr($haystack, $needle);

if ($flag){

    echo "true";
}

Bez użycia wbudowanej funkcji:

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

2
Awarie przy wyszukiwaniu pierwszego słowa.
T30

20

Miałem z tym trochę problemów i ostatecznie zdecydowałem się stworzyć własne rozwiązanie. Bez użycia silnika wyrażeń regularnych :

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

Możesz zauważyć, że poprzednie rozwiązania nie są odpowiedzią na to, że słowo jest używane jako przedrostek innego. Aby użyć swojego przykładu:

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

W powyższych przykładach zarówno $ai $bzawiera $c, ale możesz chcieć, aby twoja funkcja powiedziała ci, że $azawiera tylko $c.


1
prawdopodobnie miałeś na myśli: $found = falsena początku
spowolnienie

1
Twoja funkcja może nie działać, jeśli słowo jest połączone przecinkiem, znakiem zapytania lub kropką. np. „to, co widzisz, dostajesz”. i chcesz ustalić, czy w zdaniu jest „get”. Zwróć uwagę na kropkę obok „get”. W takim przypadku funkcja zwraca false. zaleca się użycie wyrażenia regularnego lub substratu (myślę, że i tak używa wyrażenia regularnego) do wyszukiwania / zamiany ciągów.
lightbringer

@lightbringer nie możesz się bardziej mylić ze swoją rekomendacją, co to oznacza dla Ciebie „jest zalecane”? nie ma najwyższej osoby, która by polecała lub aprowarowała. Chodzi o użycie silnika wyrażeń regularnych w php, który jest czarną dziurą w samym języku, możesz spróbować umieścić dopasowanie regex w pętli i porównać wyniki.
Decebal

Ta odpowiedź jest słabo wykazana i kończy się niepowodzeniem w przypadku wielu rozszerzonych scenariuszy. Nie widzę żadnych korzyści z rozrywki tą techniką. Oto wyrafinowana funkcja niestandardowa i iterowane wywołanie: 3v4l.org/E9dfD Nie jestem zainteresowany edycją tej wiki, ponieważ uważam, że marnowanie czasu badaczy jest marnowane.
mickmackusa

18

Inna możliwość znalezienia wystąpienia słowa z ciągu przy użyciu strstr () i stristr () jest następująca:

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

To jest wstecz. iW stristrstojaki dla nieczuły.
Adam Merrifield

18

Wiele odpowiedzi, które używają, substr_countsprawdza, czy wynik jest >0. Ale ponieważ ifinstrukcja uznaje zero za to samo co fałsz , możesz tego uniknąć i napisać bezpośrednio:

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

Aby sprawdzić, jeśli nie występuje, dodaj !operator:

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

Cóż ... częściowo prawda, w php 0 == fałsz jest prawdą, ale 0 === fałsz jest fałszem
Andrejs Gubars

17

Można to zrobić na trzy różne sposoby:

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

dobrze, ale preg_match jest ryzykowny, ponieważ może zwrócić false lub 0. Powinieneś testować dla === 1 na # 3
Zmiennokształtny

14

Wersja krótka

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

5
Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu.
Bono,

14

W celu znalezienia „słowa” zamiast wystąpienia szeregu liter, które mogą być częścią innego słowa, dobrym rozwiązaniem byłoby zastosowanie poniższego.

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

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

5
zawiedzie, jeśli $stringjestAre are, are?
Słoneczny

13

Powinieneś użyć formatu Insensitive, więc jeśli wprowadzona wartość jest w, smalllub capsnie będzie to miało znaczenia.

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

Tutaj Stripos znajduje igłę w heystacku bez rozpatrywania skrzynki (małe / czapki).

Próbka PHPCode z wyjściem


13

Może możesz użyć czegoś takiego:

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

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

12

Nie używaj, preg_match()jeśli chcesz tylko sprawdzić, czy jeden ciąg jest zawarty w innym ciągu. Użyj strpos()lub strstr()zamiast, ponieważ będą one szybsze. ( http://in2.php.net/preg_match )

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

12

Jeśli chcesz sprawdzić, czy ciąg zawiera kilka szczegółowych słów, możesz:

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

Jest to przydatne, aby uniknąć spamu na przykład podczas wysyłania wiadomości e-mail.


10

Funkcja strpos działa dobrze, ale jeśli chcesz case-insensitivesprawdzić słowo w akapicie, możesz skorzystać z striposfunkcji PHP.

Na przykład,

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

Znajdź pozycję pierwszego wystąpienia podciągu bez rozróżniania wielkości liter w ciągu.

Jeśli słowo nie istnieje w ciągu, zwróci wartość false, w przeciwnym razie zwróci pozycję słowa.


9

Musisz użyć identycznych / nie identycznych operatorów, ponieważ strpos może zwrócić 0 jako wartość indeksu. Jeśli lubisz trójskładnikowe operatory, zastanów się nad użyciem następującego (wydaje się trochę wstecz, przyznaję):

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

8

Sprawdź, czy ciąg zawiera określone słowa?

Oznacza to, że ciąg musi zostać przetłumaczony na słowa (patrz uwaga poniżej).

Jednym ze sposobów, aby to zrobić i określić separatory, jest użycie preg_split( doc ):

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

?>

Bieg daje

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

Uwaga: Nie mamy tutaj na myśli słowa dla każdej sekwencji symboli.

Praktyczną definicją słowa jest silnik wyrażeń regularnych PCRE, w którym słowa są podciągami składającymi się wyłącznie ze znaków słownych, oddzielonych znakami niebędącymi słowami.

Znak „słowo” to dowolna litera lub cyfra lub znak podkreślenia, to znaczy dowolny znak, który może być częścią „słowa” Perla. Definicja liter i cyfr jest kontrolowana przez tabele znaków PCRE i może się różnić, jeśli ma miejsce dopasowanie specyficzne dla ustawień regionalnych (..)


7

Inne rozwiązanie dla określonego ciągu:

$subject = 'How are you?';
$pattern = '/are/';
preg_match($pattern, $subject, $match);
if ($match[0] == 'are') {
    echo true;
}

Możesz także użyć strpos()funkcji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.