Considerar:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
Suponha que eu tenha o código acima, qual é a maneira correta de escrever a declaração if ($a contains 'are')
?
Considerar:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
Suponha que eu tenha o código acima, qual é a maneira correta de escrever a declaração if ($a contains 'are')
?
Respostas:
Você pode usar a strpos()
função usada para encontrar a ocorrência de uma string dentro de outra:
$a = 'How are you?';
if (strpos($a, 'are') !== false) {
echo 'true';
}
Observe que o uso de !== false
é deliberado ( != false
nem === true
retornará o resultado desejado); strpos()
retorna o deslocamento no qual a corda da agulha começa na corda do palheiro ou o booleano false
se a agulha não for encontrada. Como 0 é um deslocamento válido e 0 é "falsey", não podemos usar construções mais simples como !strpos($a, 'are')
.
strpos($a, 'are') > -1
para testar se é verdade. Do ponto de vista da depuração, acho que meu cérebro gasta menos ciclos de relógio determinando se a linha foi escrita corretamente quando não preciso contar sinais de igual contíguos.
Você pode usar expressões regulares; é melhor para a correspondência de palavras, em comparação com strpos
as mencionadas por outros usuários, e também retornará verdadeiro para strings como tarifa, assistência, olhar, etc. Isso pode ser simplesmente evitado na expressão regular usando limites de palavras.
Uma correspondência simples para are pode ser algo como isto:
$a = 'How are you?';
if (preg_match('/\bare\b/', $a)) {
echo 'true';
}
No lado do desempenho, strpos
é cerca de três vezes mais rápido e, quando eu fiz um milhão de comparações de uma só vez, foram necessários preg_match
1,5 segundos para terminar e strpos
0,5 segundos.
Editar: para pesquisar qualquer parte da string, não apenas palavra por palavra, eu recomendaria o uso de uma expressão regular como
$a = 'How are you?';
$search = 'are y';
if(preg_match("/{$search}/i", $a)) {
echo 'true';
}
A i
expressão no final da expressão regular altera a expressão regular para não diferenciar maiúsculas de minúsculas. Se você não quiser, pode deixar de fora.
Agora, isso pode ser bastante problemático em alguns casos, já que a string de pesquisa $ não é higienizada de qualquer forma, ou seja, pode não passar na verificação em alguns casos, como se $search
fosse uma entrada do usuário, eles podem adicionar uma string que possa se comportar como alguma expressão regular diferente ...
Além disso, aqui está uma ótima ferramenta para testar e ver explicações de várias expressões regulares Regex101
Para combinar os dois conjuntos de funcionalidades em uma única função multiuso (inclusive com distinção entre maiúsculas e minúsculas), você pode usar algo como isto:
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.
}
Aqui está uma pequena função utilitária que é útil em situações como esta
// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
return strpos($haystack, $needle) !== false;
}
if ($email->contains("@") && $email->endsWith(".com)) { ...
ouif (strpos($email, "@") !== false && substr($email, -strlen(".com")) == ".com") { ...
Embora a maioria dessas respostas diga se uma subcadeia aparece na sua string, geralmente não é o que você deseja se estiver procurando por uma palavra específica e não uma subcadeia .
Qual é a diferença? Substrings podem aparecer em outras palavras:
Uma maneira de atenuar isso seria usar uma expressão regular associada aos limites da palavra ( \b
):
function containsWord($str, $word)
{
return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}
Esse método não possui os mesmos falsos positivos observados acima, mas possui alguns casos extremos próprios. Limites de palavra corresponder em caracteres não-palavra ( \W
), que vão ser qualquer coisa que não é a-z
, A-Z
, 0-9
, ou _
. Isso significa que dígitos e sublinhados serão contados como caracteres de palavras e cenários como este falharão:
Se você quiser algo mais preciso do que isso, terá que começar a analisar a sintaxe no idioma inglês, e essa é uma grande lata de worms (e assume o uso adequado da sintaxe, de qualquer maneira, o que nem sempre é um dado).
\b
partidas duas coisas que \W
não, o que torna grande para encontrar palavras em uma string: Combina início da string ( ^
) e no final da string ( $
)
Para determinar se uma string contém outra, você pode usar a função 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";
}
?>
CUIDADO:
Se a agulha que você está procurando estiver no início do palheiro, ela retornará à posição 0; se você fizer uma ==
comparação que não funcione, será necessário fazer uma===
Um ==
sinal é uma comparação e testa se a variável / expressão / constante à esquerda tem o mesmo valor que a variável / expressão / constante à direita.
Um ===
sinal é uma comparação para ver se duas variáveis / expressões / constantes são iguais AND
têm o mesmo tipo - ou seja, ambas são strings ou ambas são números inteiros.
<?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($a, 'are')
é muito mais elegante que o feio strpos($a, 'are') !== false
. PHP realmente precisa de uma str_contains()
função.
Utilize a correspondência sem distinção entre maiúsculas e minúsculas usando stripos()
:
if (stripos($string,$stringToSearch) !== false) {
echo 'true';
}
Veja os comentários de SamGoody e Lego Stormtroopr.
Se você está procurando um algoritmo PHP para classificar os resultados da pesquisa com base na proximidade / relevância de várias palavras, aqui é uma maneira rápida e fácil de gerar resultados de pesquisa apenas com o PHP:
Problemas com os outros métodos boolean busca tais como strpos()
, preg_match()
, strstr()
oustristr()
Método PHP baseado no Vector Space Model e tf-idf (termo frequência - frequência inversa do documento):
Parece difícil, mas é surpreendentemente fácil.
Se queremos procurar várias palavras em uma string, o problema principal é como atribuímos um peso a cada uma delas?
Se pudéssemos ponderar os termos em uma string com base em quão representativos eles são da string como um todo, poderíamos ordenar nossos resultados pelos que melhor corresponderem à consulta.
Esta é a idéia do modelo de espaço vetorial, não muito longe de como a pesquisa de texto completo do SQL funciona:
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;
}
CASO 1
$query = 'are';
$corpus = array(
1 => 'How are you?',
);
$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
print_r($match_results);
echo '</pre>';
RESULTADO
Array
(
[1] => 0.52832083357372
)
CASO 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>';
RESULTADOS
Array
(
[1] => 0.54248125036058
[3] => 0.21699250014423
)
CASO 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>';
RESULTADOS
Array
(
[3] => 0.6813781191217
[1] => 0.54248125036058
)
Há uma abundância de melhorias a serem feitas, mas o modelo fornece uma maneira de obter bons resultados de consultas naturais, que não têm operadores booleanos tais como strpos()
, preg_match()
, strstr()
ou stristr()
.
NOTA BENE
Opcionalmente, eliminando a redundância antes de pesquisar as palavras
reduzindo assim o tamanho do índice e resultando em menos requisitos de armazenamento
menos E / S de disco
indexação mais rápida e, consequentemente, uma pesquisa mais rápida.
1. Normalização
2. Eliminação de palavras-chave
3. Substituição de dicionário
Substitua as palavras por outras que tenham um significado idêntico ou semelhante. (ex: substitua instâncias de 'fome' e 'fome' por 'fome')
Outras medidas algorítmicas (bola de neve) podem ser realizadas para reduzir ainda mais as palavras ao seu significado essencial.
A substituição de nomes de cores por seus equivalentes hexadecimais
A redução dos valores numéricos, reduzindo a precisão, são outras maneiras de normalizar o texto.
RECURSOS
Se você deseja evitar o problema "falsey" e "truth", pode usar substr_count:
if (substr_count($a, 'are') > 0) {
echo "at least one 'are' is present!";
}
É um pouco mais lento que o strpos, mas evita os problemas de comparação.
false
para "você tem certeza?" desde a posição para strpos
é0
Outra opção é usar a função strstr () . Algo como:
if (strlen(strstr($haystack,$needle))>0) {
// Needle Found
}
Ponto a observar: A função strstr () faz distinção entre maiúsculas e minúsculas. Para uma pesquisa que não diferencia maiúsculas de minúsculas, use a função stristr () .
Estou um pouco impressionado que nenhuma das respostas aqui que usou strpos
, strstr
e funções similares mencionado Funções Multibyte corda ainda (2015/05/08).
Basicamente, se estiver com problemas para encontrar palavras com caracteres específicos para alguns idiomas , como alemão, francês, português, espanhol etc. (por exemplo: ä , é , ô , ç , º , ñ ), convém preceder as funções com mb_
. Portanto, a resposta aceita usaria mb_strpos
ou mb_stripos
(para correspondência sem distinção entre maiúsculas e minúsculas):
if (mb_strpos($a,'are') !== false) {
echo 'true';
}
Se você não pode garantir que todos os seus dados sejam 100% em UTF-8 , convém usar as mb_
funções.
Um bom artigo para entender por que é o Absoluto Mínimo Todo desenvolvedor de software deve saber absolutamente, positivamente sobre Unicode e conjuntos de caracteres (sem desculpas!) De Joel Spolsky .
No PHP, a melhor maneira de verificar se uma string contém uma certa substring, é usar uma função auxiliar simples como esta:
function contains($haystack, $needle, $caseSensitive = false) {
return $caseSensitive ?
(strpos($haystack, $needle) === FALSE ? FALSE : TRUE):
(stripos($haystack, $needle) === FALSE ? FALSE : TRUE);
}
strpos
localiza a posição da primeira ocorrência de uma substring que diferencia maiúsculas de minúsculas em uma string.stripos
localiza a posição da primeira ocorrência de uma substring que não diferencia maiúsculas de minúsculas em uma string.myFunction($haystack, $needle) === FALSE ? FALSE : TRUE
garante que myFunction
sempre retorne um booleano e corrija um comportamento inesperado quando o índice da substring for 0.$caseSensitive ? A : B
seleciona strpos
ou stripos
faz o trabalho, dependendo do valor de $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)
A função abaixo também funciona e não depende de nenhuma outra função; ele usa apenas manipulação nativa de strings PHP. Pessoalmente, eu não recomendo isso, mas você pode ver como ele funciona:
<?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;
}
}
Teste:
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
Você pode usar a strstr
função:
$haystack = "I know programming";
$needle = "know";
$flag = strstr($haystack, $needle);
if ($flag){
echo "true";
}
Sem usar uma função embutida:
$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 ";
}
Eu tive alguns problemas com isso e, finalmente, escolhi criar minha própria solução. Sem usar o mecanismo de expressão regular :
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;
}
Você pode perceber que as soluções anteriores não são uma resposta para a palavra que está sendo usada como prefixo para outra. Para usar seu exemplo:
$a = 'How are you?';
$b = "a skirt that flares from the waist";
$c = "are";
Com as amostras acima, ambos $a
e $b
contém $c
, mas você pode querer que sua função diga que apenas $a
contém $c
.
$found = false
no início
Outra opção para encontrar a ocorrência de uma palavra a partir de uma string usando strstr () e stristr () é a seguinte:
<?php
$a = 'How are you?';
if (strstr($a,'are')) // Case sensitive
echo 'true';
if (stristr($a,'are')) // Case insensitive
echo 'true';
?>
i
em stristr
significa insensível.
Muitas respostas que usam substr_count
verificações se o resultado é >0
. Mas como a if
instrução considera zero igual a falso , você pode evitar essa verificação e escrever diretamente:
if (substr_count($a, 'are')) {
Para verificar se não está presente, adicione o !
operador:
if (!substr_count($a, 'are')) {
Isso pode ser feito de três maneiras diferentes:
$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
}
A versão abreviada
$result = false!==strpos($a, 'are');
Para encontrar uma 'palavra', em vez da ocorrência de uma série de letras que poderiam de fato fazer parte de outra palavra, o seguinte seria uma boa solução.
$string = 'How are you?';
$array = explode(" ", $string);
if (in_array('are', $array) ) {
echo 'Found the word';
}
$string
forAre are, are?
Você deve usar o formato Insensitive do caso, portanto, se o valor inserido estiver em small
ou caps
não importar.
<?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";
}
?>
Aqui stripos encontra agulha no palheiro sem considerar o caso (pequeno / caps).
Talvez você possa usar algo como isto:
<?php
findWord('Test all OK');
function findWord($text) {
if (strstr($text, 'ok')) {
echo 'Found a word';
}
else
{
echo 'Did not find a word';
}
}
?>
Não use preg_match()
se você deseja apenas verificar se uma sequência está contida em outra. Use strpos()
ou, em strstr()
vez disso, pois eles serão mais rápidos. ( http://in2.php.net/preg_match )
if (strpos($text, 'string_name') !== false){
echo 'get the string';
}
Se você deseja verificar se a sequência contém várias palavras específicas, você pode:
$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";
}
Isso é útil para evitar spam ao enviar e-mails, por exemplo.
A função strpos funciona bem, mas se você deseja case-insensitive
verificar uma palavra em um parágrafo, pode usar a stripos
função de PHP
.
Por exemplo,
$result = stripos("I love PHP, I love PHP too!", "php");
if ($result === false) {
// Word does not exist
}
else {
// Word exists
}
Encontre a posição da primeira ocorrência de uma substring que não diferencia maiúsculas de minúsculas em uma sequência.
Se a palavra não existir na string, ela retornará false; caso contrário, retornará a posição da palavra.
Você precisa usar operadores idênticos / não idênticos porque strpos podem retornar 0 como seu valor de índice. Se você gosta de operadores ternários, considere usar o seguinte (parece um pouco ao contrário, admito):
echo FALSE === strpos($a,'are') ? 'false': 'true';
Verifique se a string contém palavras específicas?
Isso significa que a string deve ser resolvida em palavras (veja a nota abaixo).
Uma maneira de fazer isso e especificar os separadores é usando 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');
?>
Uma corrida dá
$ 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'
Nota: Aqui não queremos dizer palavra para cada sequência de símbolos.
Uma definição prática de palavra é, no sentido, o mecanismo de expressão regular do PCRE, onde as palavras são substrings que consistem apenas em caracteres da palavra, sendo separadas por caracteres que não são da palavra.
Um caractere "palavra" é qualquer letra ou dígito ou o caractere sublinhado, ou seja, qualquer caractere que possa fazer parte de uma "palavra" Perl. A definição de letras e dígitos é controlada pelas tabelas de caracteres do PCRE e pode variar se houver correspondência específica do local (..)