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')
?
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 !== false
jest celowe (ani != false
nie === true
zwró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ą, false
jeś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')
.
strpos($a, 'are') > -1
testują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.Możesz użyć wyrażeń regularnych, lepiej pasujących do słów, niż
strpos
wspomniane 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:
Po stronie wydajności
strpos
jest około trzy razy szybsza i pamiętaj, że kiedy zrobiłem milion porównań na raz, zajęło topreg_match
1,5 sekundy, astrpos
zajęł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
Na
i
koń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ż
$search
uż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:
źródło
Oto mała funkcja użyteczna w takich sytuacjach
źródło
if ($email->contains("@") && $email->endsWith(".com)) { ...
lubif (strpos($email, "@") !== false && substr($email, -strlen(".com")) == ".com") { ...
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:
Jednym ze sposobów złagodzenia tego byłoby użycie wyrażenia regularnego połączonego z granicami słów (
\b
):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 niea-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: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).
źródło
\b
pasuje do dwóch rzeczy, które\W
nie pasują , co sprawia, że świetnie nadaje się do wyszukiwania słów w ciągu:^
$
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 ] )
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ówneAND
mają ten sam typ - czyli oba ciągi lub oba są liczbami całkowitymi.źródło
Spójrz na
strpos()
:źródło
Innym rozwiązaniem byłoby użycie
strstr()
lubstristr()
jeśli wyszukiwanie nie uwzględnia wielkości liter.źródło
strstr($a, 'are')
jest znacznie bardziej eleganckie niż brzydkiestrpos($a, 'are') !== false
. PHP naprawdę potrzebujestr_contains()
funkcji.Skorzystaj z dopasowywania bez rozróżniania wielkości liter, używając
stripos()
:źródło
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()
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:
PRZYPADEK 1
WYNIK
PRZYPADEK 2
WYNIKI
PRZYPADEK 3
WYNIKI
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()
lubstristr()
.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
2. Eliminacja słów kluczowych
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
źródło
Jeśli chcesz uniknąć problemów z „falseyem” i „prawdą”, możesz użyć substr_count:
Jest nieco wolniejszy niż strpos, ale pozwala uniknąć problemów z porównaniem.
źródło
false
„jesteś pewien?” ponieważ pozycja nastrpos
to0
Inną opcją jest użycie funkcji strstr () . Coś jak:
Uwaga: w funkcji strstr () rozróżniana jest wielkość liter. Aby wyszukiwać bez rozróżniania wielkości liter, użyj funkcji stristr () .
źródło
źródło
WARNING preg_match(): Delimiter must not be alphanumeric or backslash
Jestem pod wrażeniem, że żadna z odpowiedzi, które tu zastosowano
strpos
,strstr
i 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łabymb_strpos
lubmb_stripos
(dla dopasowania bez rozróżniania wielkości liter):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 .
źródło
W PHP najlepszym sposobem sprawdzenia, czy łańcuch zawiera określony podciąg, jest użycie prostej funkcji pomocniczej, takiej jak ta:
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 : TRUE
zapewnia, żemyFunction
zawsze zwraca wartość logiczną i naprawia nieoczekiwane zachowanie, gdy indeks podciągu wynosi 0.$caseSensitive ? A : B
wybiera albostrpos
albostripos
do wykonania pracy, w zależności od wartości$caseSensitive
.Wynik:
źródło
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:
Test:
źródło
Możesz użyć
strstr
funkcji:Bez użycia wbudowanej funkcji:
źródło
Miałem z tym trochę problemów i ostatecznie zdecydowałem się stworzyć własne rozwiązanie. Bez użycia silnika wyrażeń regularnych :
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:
W powyższych przykładach zarówno
$a
i$b
zawiera$c
, ale możesz chcieć, aby twoja funkcja powiedziała ci, że$a
zawiera tylko$c
.źródło
$found = false
na początkuInna możliwość znalezienia wystąpienia słowa z ciągu przy użyciu strstr () i stristr () jest następująca:
źródło
i
Wstristr
stojaki dla nieczuły.Wiele odpowiedzi, które używają,
substr_count
sprawdza, czy wynik jest>0
. Ale ponieważif
instrukcja uznaje zero za to samo co fałsz , możesz tego uniknąć i napisać bezpośrednio:Aby sprawdzić, jeśli nie występuje, dodaj
!
operator:źródło
Można to zrobić na trzy różne sposoby:
1- stristr ()
2- strpos ()
3- preg_match ()
źródło
Wersja krótka
źródło
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.
źródło
$string
jestAre are, are?
Powinieneś użyć formatu Insensitive, więc jeśli wprowadzona wartość jest w,
small
lubcaps
nie będzie to miało znaczenia.Tutaj Stripos znajduje igłę w heystacku bez rozpatrywania skrzynki (małe / czapki).
Próbka PHPCode z wyjściem
źródło
Może możesz użyć czegoś takiego:
źródło
Nie używaj,
preg_match()
jeśli chcesz tylko sprawdzić, czy jeden ciąg jest zawarty w innym ciągu. Użyjstrpos()
lubstrstr()
zamiast, ponieważ będą one szybsze. ( http://in2.php.net/preg_match )źródło
Jeśli chcesz sprawdzić, czy ciąg zawiera kilka szczegółowych słów, możesz:
Jest to przydatne, aby uniknąć spamu na przykład podczas wysyłania wiadomości e-mail.
źródło
Funkcja strpos działa dobrze, ale jeśli chcesz
case-insensitive
sprawdzić słowo w akapicie, możesz skorzystać zstripos
funkcjiPHP
.Na przykład,
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.
źródło
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ę):
źródło
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 ):Bieg daje
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.
źródło
Inne rozwiązanie dla określonego ciągu:
Możesz także użyć
strpos()
funkcji.źródło