Considérer:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
Supposons que j'ai le code ci-dessus, quelle est la bonne façon d'écrire l'instruction if ($a contains 'are')
?
Considérer:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
Supposons que j'ai le code ci-dessus, quelle est la bonne façon d'écrire l'instruction if ($a contains 'are')
?
Réponses:
Vous pouvez utiliser la strpos()
fonction utilisée pour rechercher l'occurrence d'une chaîne à l'intérieur d'une autre:
$a = 'How are you?';
if (strpos($a, 'are') !== false) {
echo 'true';
}
Notez que l'utilisation de !== false
est délibérée ( != false
ni === true
ne retournera le résultat souhaité); strpos()
renvoie soit l'offset auquel la chaîne d'aiguille commence dans la chaîne de botte de foin, soit le booléen false
si l'aiguille n'est pas trouvée. Puisque 0 est un décalage valide et 0 est "falsey", nous ne pouvons pas utiliser des constructions plus simples comme !strpos($a, 'are')
.
strpos($a, 'are') > -1
pour tester true. Du point de vue du débogage, je trouve que mon cerveau gaspille moins de cycles d'horloge pour déterminer si la ligne est écrite correctement quand je n'ai pas à compter les signes égaux contigus.
Vous pouvez utiliser des expressions régulières, c'est mieux pour la correspondance de mots strpos
que comme mentionné par d'autres utilisateurs, cela retournera également vrai pour les chaînes telles que le tarif, le soin, le regard, etc. Cela peut simplement être évité dans l'expression régulière en utilisant des limites de mots.
Une simple correspondance pour are pourrait ressembler à ceci:
$a = 'How are you?';
if (preg_match('/\bare\b/', $a)) {
echo 'true';
}
Du côté des performances, strpos
c'est environ trois fois plus rapide et j'ai en tête, quand j'ai fait un million de comparaisons à la fois, il a fallu preg_match
1,5 seconde pour terminer et pour strpos
cela a pris 0,5 seconde.
Edit: afin de rechercher n'importe quelle partie de la chaîne, pas seulement mot par mot, je recommanderais d'utiliser une expression régulière comme
$a = 'How are you?';
$search = 'are y';
if(preg_match("/{$search}/i", $a)) {
echo 'true';
}
À i
la fin de l'expression régulière, l'expression régulière est insensible à la casse, si vous ne le souhaitez pas, vous pouvez la laisser de côté.
Maintenant, cela peut être assez problématique dans certains cas car la chaîne de recherche $ n'est pas nettoyée de quelque façon que ce soit, je veux dire, elle peut ne pas passer la vérification dans certains cas comme s'il s'agissait d' $search
une entrée utilisateur, ils peuvent ajouter une chaîne qui pourrait se comporter comme une expression régulière différente ...
En outre, voici un excellent outil pour tester et voir les explications de diverses expressions régulières Regex101
Pour combiner les deux ensembles de fonctionnalités en une seule fonction polyvalente (y compris avec une sensibilité à la casse sélectionnable), vous pouvez utiliser quelque chose comme ceci:
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.
}
Voici une petite fonction utilitaire qui est utile dans des situations comme celle-ci
// 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") { ...
Bien que la plupart de ces réponses vous diront si une sous-chaîne apparaît dans votre chaîne, ce n'est généralement pas ce que vous voulez si vous recherchez un mot particulier , et non une sous - chaîne .
Quelle est la différence? Les sous-chaînes peuvent apparaître entre d'autres mots:
Une façon d'atténuer cela serait d'utiliser une expression régulière couplée à des limites de mots ( \b
):
function containsWord($str, $word)
{
return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}
Cette méthode n'a pas les mêmes faux positifs mentionnés ci-dessus, mais elle a ses propres cas limites. Limites correspondent mot sur les caractères non-mot ( \W
), qui vont être quelque chose qui n'est pas a-z
, A-Z
, 0-9
ou _
. Cela signifie que les chiffres et les traits de soulignement seront comptés comme des caractères de mot et que des scénarios comme celui-ci échoueront:
Si vous voulez quelque chose de plus précis que cela, vous devrez commencer à analyser la syntaxe en anglais, et c'est une très grosse boîte de vers (et suppose une utilisation correcte de la syntaxe, de toute façon, ce qui n'est pas toujours une donnée).
\b
correspond à deux choses qui \W
ne le font pas, ce qui le rend idéal pour trouver des mots dans une chaîne: il correspond au début de la chaîne ( ^
) et à la fin de la chaîne ( $
)
Pour déterminer si une chaîne contient une autre chaîne, vous pouvez utiliser la fonction 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";
}
?>
MISE EN GARDE:
Si l'aiguille que vous recherchez se trouve au début de la botte de foin, elle retournera en position 0, si vous faites une ==
comparaison qui ne fonctionnera pas, vous devrez faire un===
Un ==
signe est une comparaison et teste si la variable / expression / constante à gauche a la même valeur que la variable / expression / constante à droite.
Un ===
signe est une comparaison pour voir si deux variables / expressions / constantes sont égales AND
ont le même type - c'est-à-dire que les deux sont des chaînes ou les deux sont des entiers.
<?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.";
}
?>
Utiliser strstr()
ou stristr()
si votre recherche doit être insensible à la casse serait une autre option.
strstr($a, 'are')
est beaucoup plus élégant que le laid strpos($a, 'are') !== false
. PHP a vraiment besoin d'une str_contains()
fonction.
Utilisez la correspondance insensible à la casse en utilisant stripos()
:
if (stripos($string,$stringToSearch) !== false) {
echo 'true';
}
Regardez les commentaires de SamGoody et Lego Stormtroopr.
Si vous recherchez un algorithme PHP pour classer les résultats de recherche en fonction de la proximité / pertinence de plusieurs mots, voici un moyen rapide et facile de générer des résultats de recherche avec PHP uniquement:
Problèmes avec les autres méthodes de recherche booléenne tels que strpos()
, preg_match()
, strstr()
oustristr()
Méthode PHP basée sur le modèle d'espace vectoriel et tf-idf (terme fréquence – fréquence du document inverse):
Cela semble difficile mais étonnamment facile.
Si nous voulons rechercher plusieurs mots dans une chaîne, le problème principal est de savoir comment attribuer un poids à chacun d'eux?
Si nous pouvions pondérer les termes dans une chaîne en fonction de leur représentativité de la chaîne dans son ensemble, nous pourrions classer nos résultats par ceux qui correspondent le mieux à la requête.
C'est l'idée du modèle d'espace vectoriel, non loin du fonctionnement de la recherche SQL en texte intégral:
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;
}
CAS 1
$query = 'are';
$corpus = array(
1 => 'How are you?',
);
$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
print_r($match_results);
echo '</pre>';
RÉSULTAT
Array
(
[1] => 0.52832083357372
)
CAS 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>';
RÉSULTATS
Array
(
[1] => 0.54248125036058
[3] => 0.21699250014423
)
CAS 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>';
RÉSULTATS
Array
(
[3] => 0.6813781191217
[1] => 0.54248125036058
)
Il y a beaucoup d'améliorations à apporter , mais le modèle offre un moyen d'obtenir de bons résultats des requêtes naturelles, qui ne sont pas des opérateurs booléens tels que strpos()
, preg_match()
, strstr()
ou stristr()
.
NOTA BENE
Éliminer éventuellement la redondance avant de rechercher les mots
réduisant ainsi la taille de l'index et entraînant moins de stockage
moins d'E / S disque
indexation plus rapide et recherche par conséquent plus rapide.
1. Normalisation
2. Élimination des mots vides
3. Substitution de dictionnaire
Remplacez les mots par d'autres qui ont une signification identique ou similaire. (ex: remplacer les cas de «faim» et «faim» par «faim»)
D'autres mesures algorithmiques (boule de neige) peuvent être effectuées pour réduire davantage les mots à leur signification essentielle.
Le remplacement des noms de couleurs par leurs équivalents hexadécimaux
La réduction des valeurs numériques en réduisant la précision sont d'autres moyens de normaliser le texte.
RESSOURCES
Si vous voulez éviter le problème "falsey" et "truey", vous pouvez utiliser substr_count:
if (substr_count($a, 'are') > 0) {
echo "at least one 'are' is present!";
}
C'est un peu plus lent que strpos mais ça évite les problèmes de comparaison.
false
pour "êtes-vous sûr?" puisque le poste strpos
est0
Une autre option consiste à utiliser la fonction strstr () . Quelque chose comme:
if (strlen(strstr($haystack,$needle))>0) {
// Needle Found
}
Point à noter: la fonction strstr () est sensible à la casse. Pour une recherche non sensible à la casse, utilisez la fonction stristr () .
Je suis un peu impressionné qu'aucune des réponses ici qui a utilisé strpos
, strstr
et des fonctions similaires mentionné Fonctions Multibyte Chaîne encore (08/05/2015).
Fondamentalement, si vous rencontrez des difficultés pour trouver des mots avec des caractères spécifiques à certaines langues , tels que l'allemand, le français, le portugais, l'espagnol, etc. (par exemple: ä , é , ô , ç , º , ñ ), vous voudrez peut-être précéder les fonctions avec mb_
. Par conséquent, la réponse acceptée utiliserait mb_strpos
ou mb_stripos
(pour une correspondance insensible à la casse) à la place:
if (mb_strpos($a,'are') !== false) {
echo 'true';
}
Si vous ne pouvez pas garantir que toutes vos données sont à 100% en UTF-8 , vous pouvez utiliser les mb_
fonctions.
Un bon article pour comprendre pourquoi est le minimum absolu que tout développeur de logiciels doit absolument, positivement, connaître sur l'Unicode et les jeux de caractères (sans excuses!) Par Joel Spolsky .
En PHP, la meilleure façon de vérifier si une chaîne contient une certaine sous-chaîne, est d'utiliser une simple fonction d'aide comme celle-ci:
function contains($haystack, $needle, $caseSensitive = false) {
return $caseSensitive ?
(strpos($haystack, $needle) === FALSE ? FALSE : TRUE):
(stripos($haystack, $needle) === FALSE ? FALSE : TRUE);
}
strpos
recherche la position de la première occurrence d'une sous-chaîne sensible à la casse dans une chaîne.stripos
recherche la position de la première occurrence d'une sous-chaîne insensible à la casse dans une chaîne.myFunction($haystack, $needle) === FALSE ? FALSE : TRUE
garantit que myFunction
renvoie toujours un booléen et corrige un comportement inattendu lorsque l'index de la sous-chaîne est 0.$caseSensitive ? A : B
sélectionne soit strpos
ou stripos
pour effectuer le travail, selon la valeur 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 fonction ci-dessous fonctionne également et ne dépend d'aucune autre fonction; il utilise uniquement la manipulation de chaînes PHP native. Personnellement, je ne recommande pas cela, mais vous pouvez voir comment cela fonctionne:
<?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;
}
}
Tester:
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
Vous pouvez utiliser la strstr
fonction:
$haystack = "I know programming";
$needle = "know";
$flag = strstr($haystack, $needle);
if ($flag){
echo "true";
}
Sans utiliser de fonction intégrée:
$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 ";
}
J'ai eu quelques problèmes avec cela et j'ai finalement choisi de créer ma propre solution. Sans utiliser le moteur d' expression régulière :
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;
}
Vous pouvez remarquer que les solutions précédentes ne sont pas une réponse pour le mot utilisé comme préfixe pour un autre. Pour utiliser votre exemple:
$a = 'How are you?';
$b = "a skirt that flares from the waist";
$c = "are";
Avec les exemples ci-dessus, les deux $a
et $b
contient $c
, mais vous voudrez peut-être que votre fonction vous dise que $a
contient uniquement $c
.
$found = false
au début
Une autre option pour rechercher l'occurrence d'un mot dans une chaîne à l'aide de strstr () et stristr () est la suivante:
<?php
$a = 'How are you?';
if (strstr($a,'are')) // Case sensitive
echo 'true';
if (stristr($a,'are')) // Case insensitive
echo 'true';
?>
i
en stristr
signifie insensible.
Beaucoup de réponses qui utilisent des substr_count
contrôles si le résultat est >0
. Mais comme l' if
instruction considère zéro comme étant faux , vous pouvez éviter cette vérification et écrire directement:
if (substr_count($a, 'are')) {
Pour vérifier s'il n'est pas présent, ajoutez l' !
opérateur:
if (!substr_count($a, 'are')) {
Cela peut se faire de trois manières différentes:
$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 version courte
$result = false!==strpos($a, 'are');
Afin de trouver un «mot», plutôt que l'occurrence d'une série de lettres qui pourraient en fait faire partie d'un autre mot, ce qui suit serait une bonne solution.
$string = 'How are you?';
$array = explode(" ", $string);
if (in_array('are', $array) ) {
echo 'Found the word';
}
$string
c'estAre are, are?
Vous devez utiliser un format insensible à la casse, donc si la valeur entrée est small
ou si caps
cela n'a pas d'importance.
<?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";
}
?>
Ici, stripos trouve une aiguille dans une meule de foin sans considérer le cas (petit / casquettes).
Vous pourriez peut-être utiliser quelque chose comme ceci:
<?php
findWord('Test all OK');
function findWord($text) {
if (strstr($text, 'ok')) {
echo 'Found a word';
}
else
{
echo 'Did not find a word';
}
}
?>
Ne pas utiliser preg_match()
si vous souhaitez uniquement vérifier si une chaîne est contenue dans une autre chaîne. Utilisez strpos()
ou à la strstr()
place car ils seront plus rapides. ( http://in2.php.net/preg_match )
if (strpos($text, 'string_name') !== false){
echo 'get the string';
}
Si vous voulez vérifier si la chaîne contient plusieurs mots spécifiques, vous pouvez faire:
$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";
}
C'est utile pour éviter le spam lors de l'envoi d'emails par exemple.
La fonction strpos fonctionne bien, mais si vous voulez case-insensitive
vérifier un mot dans un paragraphe, vous pouvez utiliser la stripos
fonction de PHP
.
Par exemple,
$result = stripos("I love PHP, I love PHP too!", "php");
if ($result === false) {
// Word does not exist
}
else {
// Word exists
}
Trouvez la position de la première occurrence d'une sous-chaîne insensible à la casse dans une chaîne.
Si le mot n'existe pas dans la chaîne, il retournera false sinon il renverra la position du mot.
Vous devez utiliser des opérateurs identiques / non identiques car strpos peut renvoyer 0 comme valeur d'index. Si vous aimez les opérateurs ternaires, pensez à utiliser ce qui suit (semble un peu en arrière, je l'admets):
echo FALSE === strpos($a,'are') ? 'false': 'true';
Vérifiez si la chaîne contient des mots spécifiques?
Cela signifie que la chaîne doit être résolue en mots (voir la note ci-dessous).
Une façon de le faire et de spécifier les séparateurs utilise 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');
?>
Une course donne
$ 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'
Remarque: Ici, nous ne voulons pas dire mot pour chaque séquence de symboles.
Une définition pratique du mot est en ce sens que le moteur d'expression régulière PCRE, où les mots sont des sous-chaînes constituées uniquement de caractères de mot, étant séparés par des caractères non-mot.
Un caractère "mot" est une lettre ou un chiffre ou le caractère de soulignement, c'est-à-dire tout caractère pouvant faire partie d'un "mot" Perl. La définition des lettres et des chiffres est contrôlée par les tables de caractères de PCRE et peut varier si une correspondance spécifique aux paramètres régionaux a lieu (..)