Как проверить, содержит ли строка определенное слово?
Рассматривать:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
Предположим, у меня есть код выше, как правильно написать заявление if ($a contains 'are')
?
36 ответов
Вы можете использовать strpos()
функция, которая используется, чтобы найти вхождение одной строки в другую:
$a = 'How are you?';
if (strpos($a, 'are') !== false) {
echo 'true';
}
Обратите внимание, что использование !== false
намеренно; strpos()
возвращает либо смещение, с которого начинается строка иглы в строке сена, либо логическое значение false
если игла не найдена. Так как 0 является допустимым смещением, а 0 - "ложным", мы не можем использовать более простые конструкции, такие как !strpos($a, 'are')
,
Вы можете использовать регулярные выражения, лучше для сопоставления слов по сравнению с strpos, как уже упоминалось другими пользователями, он также будет возвращать true для таких строк, как стоимость, уход, взгляд и т. Д. Этого можно просто избежать в регулярном выражении, используя границы слов.
Простое совпадение для может выглядеть примерно так:
$a = 'How are you?';
if (preg_match('/\bare\b/', $a)) {
echo 'true';
}
Что касается производительности, strpos работает примерно в три раза быстрее, и я имею в виду, что когда я сделал миллион сравнений одновременно, потребовалось preg_match
1,5 секунды, чтобы закончить, и для strpos это заняло 0,5 секунды.
Изменить: для поиска любой части строки, а не только слово за словом, я бы рекомендовал использовать регулярное выражение, как
$a = 'How are you?';
$search 'are y';
if(preg_match("/{$search}/i", $a)) {
echo 'true';
}
i
в конце регулярного выражения меняет регулярное выражение на нечувствительное к регистру, если вы этого не хотите, вы можете его пропустить.
Теперь это может быть довольно проблематично в некоторых случаях, поскольку строка поиска $ в любом случае не очищается, я имею в виду, что в некоторых случаях она может не пройти проверку, как если бы $search
пользовательский ввод, они могут добавить строку, которая может вести себя как другое регулярное выражение...
Также, вот отличный инструмент для тестирования и просмотра объяснений различных регулярных выражений Regex101.
Вот небольшая полезная функция, которая полезна в подобных ситуациях
// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
return strpos($haystack, $needle) !== false;
}
Чтобы определить, содержит ли строка другую строку, вы можете использовать функцию 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
имеют одинаковый тип - т.е. оба являются строками или оба являются целыми числами.
Хотя большинство из этих ответов скажут вам, появляется ли подстрока в вашей строке, обычно это не то, что вам нужно, если вы ищете определенное слово, а не подстроку.
Какая разница? Подстроки могут появляться в других словах:
- "Есть" в начале "области"
- "Есть" в конце "заяц"
- "Есть" в середине "тарифы"
Одним из способов смягчения этого было бы использование регулярного выражения в сочетании с границами слова (\b
):
function containsWord($str, $word)
{
return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}
Этот метод не имеет таких же ложных срабатываний, как отмечалось выше, но у него есть некоторые собственные крайние случаи. Границы слов совпадают на несловесных символах (\W
), которые будут чем-то, что не a-z
, A-Z
, 0-9
, или же _
, Это означает, что цифры и подчеркивания будут учитываться как символы слова, и сценарии, подобные этому, потерпят неудачу:
- "Есть" в "Что _are_ вы думаете?"
- "Есть" в "LOL 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.";
}
?>
С помощью strstr()
или же stristr()
если ваш поиск должен быть без учета регистра, был бы другой вариант.
Посмотрите на комментарии SamGoody и Lego Stormtroopr.
Если вы ищете алгоритм PHP для ранжирования результатов поиска на основе близости / релевантности нескольких слов, здесь вы найдете быстрый и простой способ получения результатов поиска только с помощью PHP:
Проблемы с другими булевыми методами поиска, такими как strpos()
, preg_match()
, strstr()
или же stristr()
- не могу найти несколько слов
- результаты не оценены
Метод PHP, основанный на модели векторного пространства и 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()
,
НОТА БЕНЕ
Опционально устранение избыточности перед поиском по словам
тем самым уменьшая размер индекса и приводя к меньшему требованию к памяти
меньше дискового ввода / вывода
более быстрая индексация и, следовательно, более быстрый поиск.
1. Нормализация
- Преобразовать весь текст в нижний регистр
2. Стоп-лосс
- Исключите из текста слова, которые не имеют реального значения (например, "и", "или", "the", "for" и т. Д.)
3. Подстановка словаря
Замените слова другими словами, имеющими одинаковое или похожее значение. (например: заменить случаи "голодный" и "голодный" на "голод")
Дальнейшие алгоритмические меры (снежный ком) могут быть выполнены для дальнейшего приведения слов к их существенному значению.
Замена имен цветов их шестнадцатеричными эквивалентами
Сокращение числовых значений за счет снижения точности являются другими способами нормализации текста.
РЕСУРСЫ
- http://linuxgazette.net/164/sephton.html
- http://snowball.tartarus.org/
- Объясненная оценка полнотекстового поиска MySQL
- http://dev.mysql.com/doc/internals/en/full-text-search.html
- http://en.wikipedia.org/wiki/Vector_space_model
- http://en.wikipedia.org/wiki/Tf%E2%80%93idf
- http://phpir.com/simple-search-the-vector-space-model/
Используйте сопоставление без учета регистра, используя stripos()
:
if (stripos($string,$stringToSearch) !== false) {
echo 'true';
}
Если вы хотите избежать проблем "фальси" и "правдивости", вы можете использовать substr_count:
if (substr_count($a, 'are') > 0) {
echo "at least one 'are' is present!";
}
Это немного медленнее, чем strpos, но позволяет избежать проблем со сравнением.
Другой вариант - использовать функцию strstr(). Что-то вроде:
if (strlen(strstr($haystack,$needle))>0) {
// Needle Found
}
Обратите внимание: функция strstr() чувствительна к регистру. Для поиска без учета регистра используйте функцию stristr().
Я немного впечатлен, что ни один из ответов здесь, которые использовали strpos
, strstr
и аналогичные функции упомянутые функции многобайтовой строки еще (2015-05-08).
В основном, если у вас возникают проблемы с поиском слов с символами, характерными для некоторых языков, например, немецкого, французского, португальского, испанского и т. Д. (Например, ä, é, ô, ç, º, ñ), вам может потребоваться предшествовать функции с mb_
, Поэтому принятый ответ будет использовать mb_strpos
или же mb_stripos
(для сопоставления без учета регистра) вместо этого:
if (mb_strpos($a,'are') !== false) {
echo 'true';
}
Если вы не можете гарантировать, что все ваши данные на 100% в UTF-8, вы можете использовать mb_
функции.
Хорошая статья, чтобы понять, почему Абсолютный Минимум, Каждый Разработчик Программного Обеспечения Абсолютно, Положительно Должен Знать О Юникоде и Наборах Символов (Никаких Оправданий!) От Джоэла Спольски.
В 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
всегда возвращает логическое значение и исправляет непредвиденное поведение, когда индекс подстроки равен 0.$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)
Вы можете использовать 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 ";
}
Много ответов, которые используют substr_count
проверяет, если результат >0
, Но так как if
оператор считает ноль тем же, что и ложь, вы можете избежать этой проверки и написать напрямую:
if (substr_count($a, 'are')) {
Чтобы проверить, если нет, добавьте !
оператор:
if (!substr_count($a, 'are')) {
Функция ниже также работает и не зависит от какой-либо другой функции; он использует только нативную обработку строк 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
У меня были некоторые проблемы с этим, и, наконец, я решил создать свое собственное решение. Без использования механизма регулярных выражений:
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
,
Это можно сделать тремя разными способами:
$a = 'How are you?';
1-стристр ()
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
}
Не использовать preg_match()
если вы хотите проверить, содержится ли одна строка в другой. использование strpos()
или же strstr()
вместо этого, поскольку они будут быстрее. ( http://in2.php.net/preg_match)
if (strpos($text, 'string_name') !== false){
echo 'get the string';
}
Чтобы найти "слово", а не набор букв, которые на самом деле могли бы быть частью другого слова, хорошим решением будет следующее.
$string = 'How are you?';
$array = explode(" ", $string);
if (in_array('are', $array) ) {
echo 'Found the word';
}
Вы должны использовать регистр без учета регистра, поэтому, если введенное значение находится в small
или же caps
это не имеет значения.
<?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";
}
?>
Здесь стрипос находит иголку в стоге сена без учета случая (маленький / колпачки).
Может быть, вы могли бы использовать что-то вроде этого:
<?php
findWord('Test all OK');
function findWord($text) {
if (strstr($text, 'ok')) {
echo 'Found a word';
}
else
{
echo 'Did not find a word';
}
}
?>
Если вы хотите проверить, содержит ли строка несколько специфических слов, вы можете сделать:
$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";
}
Это полезно, чтобы избежать спама при отправке электронных писем, например.
Строка может быть проверена с помощью следующей функции:
function either_String_existor_not($str, $character) {
if (strpos($str, $character) !== false) {
return true;
}
return false;
}
Функция strpos работает нормально, но если вы хотите сделать case-insensitive
проверяя слово в абзаце, вы можете использовать stripos
функция PHP
,
Например,
$result = stripos("I love PHP, I love PHP too!", "php");
if ($result === false) {
// Word does not exist
}
else {
// Word exists
}
Найти позицию первого вхождения нечувствительной к регистру подстроки в строке.
Если слово не существует в строке, оно вернет false, иначе вернет позицию слова.
Вам нужно использовать идентичные / не идентичные операторы, потому что strpos может вернуть 0 в качестве значения индекса. Если вам нравятся троичные операторы, подумайте над тем, чтобы использовать следующее (я думаю, что это немного задом наперед):
echo FALSE === strpos($a,'are') ? 'false': 'true';
Проверить, содержит ли строка конкретные слова?
Это означает, что строка должна быть преобразована в слова (см. Примечание ниже).
Одним из способов сделать это и указать разделители является использование preg_split
( док):
<?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');
?>
Бег дает
$ 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'
Примечание: здесь мы не подразумеваем слово для каждой последовательности символов.
Практическим определением слова является в этом смысле механизм регулярных выражений PCRE, где слова - это подстроки, состоящие только из символов слова, разделенные несловесными символами.
Символ "слово" - это любая буква или цифра или символ подчеркивания, то есть любой символ, который может быть частью Perl-слова. Определение букв и цифр контролируется таблицами символов PCRE и может отличаться, если происходит сопоставление для конкретной локали (..)