Considerar:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
Supongamos que tengo el código anterior, ¿cuál es la forma correcta de escribir la declaración if ($a contains 'are')
?
Considerar:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
Supongamos que tengo el código anterior, ¿cuál es la forma correcta de escribir la declaración if ($a contains 'are')
?
Respuestas:
Puede usar la strpos()
función que se usa para encontrar la aparición de una cadena dentro de otra:
$a = 'How are you?';
if (strpos($a, 'are') !== false) {
echo 'true';
}
Tenga en cuenta que el uso de !== false
es deliberado ( != false
ni === true
devolverá el resultado deseado); strpos()
devuelve el desplazamiento en el que comienza la secuencia de agujas en la secuencia de pajar o el valor booleano false
si no se encuentra la aguja. Como 0 es un desplazamiento válido y 0 es "falsey", no podemos usar construcciones más simples como !strpos($a, 'are')
.
strpos($a, 'are') > -1
para probar si es verdadero. Desde una perspectiva de depuración, encuentro que mi cerebro desperdicia menos ciclos de reloj para determinar si la línea está escrita correctamente cuando no tengo que contar signos iguales contiguos.
Puede usar expresiones regulares, es mejor para la coincidencia de palabras en comparación con strpos
lo mencionado por otros usuarios, también devolverá verdadero para cadenas como tarifa, cuidado, mirada fija, etc. Esto simplemente se puede evitar en la expresión regular mediante el uso de límites de palabras.
Una coincidencia simple para se podría ver más o menos así:
$a = 'How are you?';
if (preg_match('/\bare\b/', $a)) {
echo 'true';
}
Por el lado del rendimiento, strpos
es aproximadamente tres veces más rápido y tenga en cuenta que cuando hice un millón de comparaciones a la vez, tardé preg_match
1.5 segundos en terminar y para strpos
0.5 segundos.
Editar: para buscar cualquier parte de la cadena, no solo palabra por palabra, recomendaría usar una expresión regular como
$a = 'How are you?';
$search = 'are y';
if(preg_match("/{$search}/i", $a)) {
echo 'true';
}
El i
final de la expresión regular cambia la expresión regular para que no distinga entre mayúsculas y minúsculas, si no lo desea, puede omitirlo.
Ahora, esto puede ser bastante problemático en algunos casos ya que la cadena de búsqueda $ no está desinfectada de ninguna manera, es decir, puede que no pase la verificación en algunos casos, ya que si $search
es una entrada del usuario, pueden agregar alguna cadena que podría comportarse como alguna expresión regular diferente ...
Además, aquí hay una gran herramienta para probar y ver explicaciones de varias expresiones regulares Regex101
Para combinar ambos conjuntos de funciones en una sola función multipropósito (incluso con mayúsculas y minúsculas seleccionables), puede usar algo como esto:
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.
}
Aquí hay una pequeña función de utilidad que es útil en situaciones 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)) { ...
oif (strpos($email, "@") !== false && substr($email, -strlen(".com")) == ".com") { ...
Si bien la mayoría de estas respuestas le dirán si aparece una subcadena en su cadena, eso generalmente no es lo que desea si está buscando una palabra en particular , y no una subcadena .
¿Cual es la diferencia? Las subcadenas pueden aparecer en otras palabras:
Una forma de mitigar esto sería usar una expresión regular junto con límites de palabras ( \b
):
function containsWord($str, $word)
{
return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}
Este método no tiene los mismos falsos positivos mencionados anteriormente, pero tiene algunos casos extremos propios. Límites de las palabras coinciden en caracteres que no son de texto ( \W
), que van a ser cualquier cosa que no es a-z
, A-Z
, 0-9
, o _
. Eso significa que los dígitos y los guiones bajos se contarán como caracteres de palabras y escenarios como este fallarán:
Si desea algo más preciso que esto, tendrá que comenzar a analizar la sintaxis del idioma inglés, y esa es una lata bastante grande de gusanos (y supone un uso adecuado de la sintaxis, lo cual no siempre es un hecho).
\b
coincide con dos cosas que \W
no lo hacen, lo que lo hace ideal para encontrar palabras en una cadena: coincide con el comienzo de la cadena ( ^
) y el final de la cadena ( $
)
Para determinar si una cadena contiene otra cadena, puede usar la función 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";
}
?>
PRECAUCIÓN:
Si la aguja que está buscando está al comienzo del pajar, volverá a la posición 0, si realiza una ==
comparación que no funcionará, deberá hacer un===
Un ==
signo es una comparación y prueba si la variable / expresión / constante a la izquierda tiene el mismo valor que la variable / expresión / constante a la derecha.
Un ===
signo es una comparación para ver si dos variables / expresiones / constantes son iguales AND
tienen el mismo tipo, es decir, ambas son cadenas o ambas son enteros.
<?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.";
}
?>
Usar strstr()
o stristr()
si su búsqueda no distingue entre mayúsculas y minúsculas sería otra opción.
strstr($a, 'are')
es mucho más elegante que lo feo strpos($a, 'are') !== false
. PHP realmente necesita una str_contains()
función.
Utilice la coincidencia entre mayúsculas y minúsculas utilizando stripos()
:
if (stripos($string,$stringToSearch) !== false) {
echo 'true';
}
Mira los comentarios de SamGoody y Lego Stormtroopr.
Si está buscando un algoritmo PHP para clasificar los resultados de búsqueda en función de la proximidad / relevancia de varias palabras, aquí viene una manera rápida y fácil de generar resultados de búsqueda solo con PHP:
Problemas con los otros métodos de búsqueda booleana como strpos()
, preg_match()
, strstr()
ostristr()
Método PHP basado en el modelo de espacio vectorial y tf-idf (término frecuencia-frecuencia de documento inversa):
Suena difícil pero es sorprendentemente fácil.
Si queremos buscar varias palabras en una cadena, el problema central es cómo asignamos un peso a cada una de ellas.
Si pudiéramos ponderar los términos en una cadena en función de cuán representativos son de la cadena en su conjunto, podríamos ordenar nuestros resultados por los que mejor coincidan con la consulta.
Esta es la idea del modelo de espacio vectorial, no muy lejos de cómo funciona la búsqueda de texto completo de 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;
}
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
)
Hay un montón de mejoras a realizar, pero el modelo proporciona una manera de conseguir buenos resultados de las consultas naturales, que no tienen los operadores booleanos tales como strpos()
, preg_match()
, strstr()
o stristr()
.
NOTA BENE
Opcionalmente eliminando la redundancia antes de buscar las palabras
reduciendo así el tamaño del índice y resultando en un menor requerimiento de almacenamiento
menos E / S de disco
indexación más rápida y consecuentemente una búsqueda más rápida.
1. Normalización
2. Eliminación de palabras vacías
3. Sustitución del diccionario
Reemplace las palabras con otras que tengan un significado idéntico o similar. (por ejemplo: reemplace las instancias de 'hambriento' y 'hambriento' con 'hambre')
Se pueden realizar otras medidas algorítmicas (bola de nieve) para reducir aún más las palabras a su significado esencial.
La sustitución de nombres de colores con sus equivalentes hexadecimales
La reducción de valores numéricos al reducir la precisión son otras formas de normalizar el texto.
RECURSOS
Si desea evitar el problema "falsey" y "verdadero", puede usar substr_count:
if (substr_count($a, 'are') > 0) {
echo "at least one 'are' is present!";
}
Es un poco más lento que strpos pero evita los problemas de comparación.
false
para "¿estás seguro?" ya que la posición para strpos
es0
Otra opción es usar la función strstr () . Algo como:
if (strlen(strstr($haystack,$needle))>0) {
// Needle Found
}
Punto a tener en cuenta: la función strstr () distingue entre mayúsculas y minúsculas. Para una búsqueda que no distingue entre mayúsculas y minúsculas, use la función stristr () .
Estoy un poco impresionado de que ninguna de las respuestas que usé aquí strpos
, strstr
y funciones similares mencionen las funciones de cadena multibyte todavía (2015-05-08).
Básicamente, si tiene problemas para encontrar palabras con caracteres específicos de algunos idiomas , como alemán, francés, portugués, español, etc. (por ejemplo: ä , é , ô , ç , º , ñ ), es posible que desee preceder las funciones con mb_
. Por lo tanto, la respuesta aceptada usaría mb_strpos
o mb_stripos
(para la coincidencia entre mayúsculas y minúsculas) en su lugar:
if (mb_strpos($a,'are') !== false) {
echo 'true';
}
Si no puede garantizar que todos sus datos estén al 100% en UTF-8 , puede utilizar las mb_
funciones.
Un buen artículo para entender por qué es El mínimo absoluto que todo desarrollador de software debe saber absolutamente, positivamente sobre Unicode y los conjuntos de caracteres (¡Sin excusas!) Por Joel Spolsky .
En PHP, la mejor manera de verificar si una cadena contiene una determinada subcadena es usar una función auxiliar simple como esta:
function contains($haystack, $needle, $caseSensitive = false) {
return $caseSensitive ?
(strpos($haystack, $needle) === FALSE ? FALSE : TRUE):
(stripos($haystack, $needle) === FALSE ? FALSE : TRUE);
}
strpos
encuentra la posición de la primera aparición de una subcadena sensible a mayúsculas y minúsculas en una cadena.stripos
encuentra la posición de la primera aparición de una subcadena insensible a mayúsculas y minúsculas en una cadena.myFunction($haystack, $needle) === FALSE ? FALSE : TRUE
garantiza que myFunction
siempre devuelve un valor booleano y corrige un comportamiento inesperado cuando el índice de la subcadena es 0.$caseSensitive ? A : B
selecciona ya sea strpos
o stripos
para hacer el trabajo, dependiendo del 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)
La siguiente función también funciona y no depende de ninguna otra función; usa solo manipulación de cadenas PHP nativas. Personalmente, no recomiendo esto, pero puedes ver cómo 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;
}
}
Prueba:
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
Puedes usar la strstr
función:
$haystack = "I know programming";
$needle = "know";
$flag = strstr($haystack, $needle);
if ($flag){
echo "true";
}
Sin usar una función incorporada:
$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 ";
}
Tuve algunos problemas con esto y finalmente elegí crear mi propia solución. Sin usar el motor de expresión 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;
}
Puede notar que las soluciones anteriores no son una respuesta para la palabra que se usa como prefijo para otra. Para usar su ejemplo:
$a = 'How are you?';
$b = "a skirt that flares from the waist";
$c = "are";
Con los ejemplos anteriores, ambos $a
y $b
contiene $c
, pero es posible que desee que su función le diga que solo $a
contiene $c
.
$found = false
al principio
Otra opción para encontrar la aparición de una palabra de una cadena usando strstr () y stristr () es la siguiente:
<?php
$a = 'How are you?';
if (strstr($a,'are')) // Case sensitive
echo 'true';
if (stristr($a,'are')) // Case insensitive
echo 'true';
?>
i
en stristr
significa insensible.
Muchas respuestas que usan substr_count
cheques si el resultado es >0
. Pero como la if
declaración considera cero igual a falso , puede evitar ese cheque y escribir directamente:
if (substr_count($a, 'are')) {
Para verificar si no está presente, agregue el !
operador:
if (!substr_count($a, 'are')) {
Se puede hacer de tres maneras 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
}
La versión abreviada
$result = false!==strpos($a, 'are');
Para encontrar una 'palabra', en lugar de la aparición de una serie de letras que de hecho podrían ser parte de otra palabra, lo siguiente sería una buena solución.
$string = 'How are you?';
$array = explode(" ", $string);
if (in_array('are', $array) ) {
echo 'Found the word';
}
$string
esAre are, are?
Debe usar el formato de mayúsculas y minúsculas, por lo que si el valor ingresado está en small
o caps
no 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";
}
?>
Aquí stripos encuentra la aguja en el heystack sin considerar el caso (pequeño / tapas).
Tal vez podrías usar algo como esto:
<?php
findWord('Test all OK');
function findWord($text) {
if (strstr($text, 'ok')) {
echo 'Found a word';
}
else
{
echo 'Did not find a word';
}
}
?>
No lo use preg_match()
si solo desea verificar si una cadena está contenida en otra cadena. Use strpos()
o en su strstr()
lugar ya que serán más rápidos. ( http://in2.php.net/preg_match )
if (strpos($text, 'string_name') !== false){
echo 'get the string';
}
Si desea verificar si la cadena contiene varias palabras específicas, puede hacer:
$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";
}
Esto es útil para evitar el spam cuando se envían correos electrónicos, por ejemplo.
La función strpos funciona bien, pero si desea case-insensitive
verificar una palabra en un párrafo, puede utilizar la stripos
función de PHP
.
Por ejemplo,
$result = stripos("I love PHP, I love PHP too!", "php");
if ($result === false) {
// Word does not exist
}
else {
// Word exists
}
Encuentre la posición de la primera aparición de una subcadena insensible a mayúsculas y minúsculas en una cadena.
Si la palabra no existe en la cadena, devolverá falso, de lo contrario devolverá la posición de la palabra.
Debe usar operadores idénticos / no idénticos porque strpos puede devolver 0 como su valor de índice. Si le gustan los operadores ternarios, considere usar lo siguiente (parece un poco al revés, lo admito):
echo FALSE === strpos($a,'are') ? 'false': 'true';
¿Comprobar si la cadena contiene palabras específicas?
Esto significa que la cadena debe resolverse en palabras (vea la nota a continuación).
Una forma de hacer esto y especificar los separadores es usar 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');
?>
Una carrera da
$ 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: Aquí no queremos decir palabra para cada secuencia de símbolos.
Una definición práctica de palabra es, en el sentido, el motor de expresión regular PCRE, donde las palabras son subcadenas que consisten solo en caracteres de palabras, separadas por caracteres que no son palabras.
Un carácter de "palabra" es cualquier letra o dígito o el carácter de subrayado, es decir, cualquier carácter que puede ser parte de una "palabra" de Perl. La definición de letras y dígitos está controlada por las tablas de caracteres de PCRE, y puede variar si se realiza una coincidencia específica de la localidad (..)