Comment puis-je écrire deux fonctions qui prendraient une chaîne et retourneraient si elle commence par le caractère / chaîne spécifié ou se termine par elle?
Par exemple:
$str = '|apples}';
echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
s($str)->startsWith('|')
ets($str)->endsWith('}')
utile, comme on le trouve dans cette bibliothèque autonome .Réponses:
Utilisez-le si vous ne souhaitez pas utiliser d'expression régulière.
la source
$length
n'est pas nécessaire dans la dernière ligne duendsWith()
.return substr($haystack, -strlen($needle))===$needle;
if
tout en passant$length
le troisième paramètre àsubstr
:return (substr($haystack, -$length, $length);
. Cela gère le cas de$length == 0
en retournant une chaîne vide et non la totalité$haystack
.Vous pouvez utiliser la
substr_compare
fonction pour vérifier au début et à la fin:Cela devrait être l'une des solutions les plus rapides sur PHP 7 ( script de référence ). Testé contre des meules de foin de 8 Ko, des aiguilles de différentes longueurs et des étuis complets, partiels et sans correspondance.
strncmp
est un peu plus rapide pour les débuts avec mais il ne peut pas vérifier les fins avec.la source
strrpos
ce qui (devrait) échouer immédiatement si l'aiguille ne correspond pas au début de la botte de foin.-strlength($haystack)
) et recherchons en arrière à partir de là? Cela ne veut-il pas dire que vous ne cherchez rien? Je ne comprends pas non plus les!== false
parties de cela. Je suppose que cela repose sur une bizarrerie de PHP où certaines valeurs sont "véridiques" et d'autres "fausses", mais comment cela fonctionne-t-il dans ce cas?xxxyyy
needle =yyy
et l'utilisation destrrpos
la recherche commence à partir du premierx
. Maintenant, nous n'avons pas de correspondance réussie ici (trouvé x au lieu de y) et nous ne pouvons plus revenir en arrière (nous sommes au début de la chaîne), la recherche échoue immédiatement . À propos de l'utilisation!== false
-strrpos
dans l'exemple ci-dessus, renvoie 0 ou false et pas une autre valeur. De même,strpos
dans l'exemple ci-dessus, peut retourner$temp
(la position attendue) ou false. Je suis allé avec!== false
cohérence, mais vous pouvez utiliser=== 0
et=== $temp
dans les fonctions respectivement.Mis à jour le 23 août 2016
Les fonctions
Les tests
Résultats (PHP 7.0.9)
(Trié du plus rapide au plus lent)
Résultats (PHP 5.3.29)
(Trié du plus rapide au plus lent)
startswith_benchmark.php
la source
function startswith5b($haystack, $needle) {return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;}
j'ai ajouté une réponse ci-dessous.Toutes les réponses semblent à ce jour pour faire des charges de travail inutile,
strlen calculations
,string allocations (substr)
, etc.'strpos'
et'stripos'
fonctions renvoient l'index de la première occurrence de$needle
dans$haystack
:la source
endsWith()
la fonction a une erreur. Sa première ligne devrait être (sans le -1):$expectedPosition = strlen($haystack) - strlen($needle);
strpos($haystack, "$needle", 0)
s'il y avait une chance que ce ne soit pas déjà une chaîne (par exemple, si elle venaitjson_decode()
). Sinon, le comportement par défaut [étrange] destrpos()
peut entraîner des résultats inattendus: " Si l'aiguille n'est pas une chaîne, elle est convertie en entier et appliquée comme valeur ordinale d'un caractère. "Crédit à :
Vérifiez si une chaîne se termine par une autre chaîne
Vérifiez si une chaîne commence par une autre chaîne
la source
Le regex fonctionne ci-dessus, mais avec les autres modifications également suggérées ci-dessus:
la source
Cette question a déjà de nombreuses réponses, mais dans certains cas, vous pouvez vous contenter de quelque chose de plus simple que tous. Si la chaîne que vous recherchez est connue (codée en dur), vous pouvez utiliser des expressions régulières sans aucune citation, etc.
Vérifiez si une chaîne commence par 'ABC':
se termine par 'ABC':
Dans mon cas simple, je voulais vérifier si une chaîne se termine par une barre oblique:
L'avantage: comme c'est très court et simple, vous n'avez pas à définir de fonction (comme
endsWith()
) comme indiqué ci-dessus.Mais encore une fois - ce n'est pas une solution pour chaque cas, juste celui très spécifique.
la source
@
, de sorte que la barre oblique (/
) ne doive pas être échappée. Voir l'exemple # 3 ici: php.net/manual/en/function.preg-match.php .Si la vitesse est importante pour vous, essayez ceci (je pense que c'est la méthode la plus rapide)
Fonctionne uniquement pour les chaînes et si $ haystack ne contient qu'un seul caractère
la source
endsWithChar('','x')
mais le résultat est correctVoici deux fonctions qui n'introduisent pas de chaîne temporaire, ce qui pourrait être utile lorsque les aiguilles sont sensiblement grosses:
la source
endsWidth
devrait fairereturn $needle==='' || substr_compare(
... donc ça marche comme prévu pour-strlen($needle)===0
qui, sans le correctif, faitendsWith('a','')
retourfalse
substr_compare()
fait, j'ai donc ajouté un PR pour résoudre ce problème :)endsWith('', 'foo')
déclenche un avertissement: «substr_compare (): la position de départ ne peut pas dépasser la longueur de chaîne initiale». C'est peut-être un autre bugsubstr_compare()
, mais pour l'éviter, vous avez besoin d'une pré-vérification comme ...|| (strlen($needle) <= strlen($haystack) && substr_compare(
...) === 0);
return $needle === '' || @substr_compare(
.. pour supprimer cet avertissement.Extrémités les plus rapides Avec la solution ():
Référence:
Résultats de référence:
la source
Je me rends compte que cela a été terminé, mais vous voudrez peut-être regarder strncmp car il vous permet de mettre la longueur de la chaîne à comparer, donc:
la source
Vous pouvez utiliser
strpos
etstrrpos
la source
strpos($sHaystack, $sNeedle) == 0
comme çastrpos($sHaystack, $sNeedle) === 0
? Je vois un bug lors de l'false == 0
évaluationtrue
.Voici une version sûre à plusieurs octets de la réponse acceptée, cela fonctionne bien pour les chaînes UTF-8:
la source
startsWith
ce devrait être$length = mb_strlen($needle, 'UTF-8');
Des lignes simples courtes et faciles à comprendre sans expressions régulières.
startsWith () est simple.
endsWith () utilise le strrev () légèrement fantaisie et lent:
la source
En se concentrant sur les débuts, si vous êtes sûr que les chaînes ne sont pas vides, ajouter un test sur le premier caractère, avant la comparaison, le strlen, etc., accélère un peu les choses:
C'est en quelque sorte (20% -30%) plus rapide. L'ajout d'un autre test de caractère, comme $ haystack {1} === $ needle {1} ne semble pas accélérer beaucoup les choses, voire ralentir.
===
semble plus rapide que l'==
opérateur conditionnel(a)?b:c
semble plus rapide queif(a) b; else c;
Pour ceux qui demandent "pourquoi ne pas utiliser des strpos?" qualifier d'autres solutions de "travail inutile"
strpos est rapide, mais ce n'est pas le bon outil pour ce travail.
Pour comprendre, voici une petite simulation à titre d'exemple:
Que fait l'ordinateur "à l'intérieur"?
En supposant que strlen n'itère pas la chaîne entière (mais même dans ce cas), cela n'est pas du tout pratique.
la source
J'espère que la réponse ci-dessous sera efficace et aussi simple:
la source
Je finis généralement par utiliser une bibliothèque comme underscore-php de nos jours.
La bibliothèque regorge d'autres fonctions pratiques.
la source
La réponse de mpen est incroyablement approfondie, mais, malheureusement, l'indice de référence fourni a une surveillance très importante et préjudiciable.
Étant donné que chaque octet dans les aiguilles et les meules de foin est complètement aléatoire, la probabilité qu'une paire aiguille-meule de foin diffère sur le tout premier octet est de 99,609375%, ce qui signifie qu'en moyenne, environ 99609 des 100000 paires différeront sur le tout premier octet. . En d'autres termes, l'indice de référence est fortement biaisé vers les
startswith
implémentations qui vérifient explicitement le premier octet, comme lestrncmp_startswith2
fait.Si la boucle de génération de test est à la place implémentée comme suit:
les résultats de référence racontent une histoire légèrement différente:
Bien sûr, ce point de référence n'est peut-être pas encore parfaitement impartial, mais il teste également l'efficacité des algorithmes lorsqu'ils reçoivent des aiguilles partiellement correspondantes.
la source
en bref:
la source
Juste une recommandation:
Cette ligne supplémentaire, comparant le premier caractère des chaînes, peut faire revenir la fausse casse immédiatement , rendant ainsi beaucoup de vos comparaisons beaucoup plus rapides (7 fois plus rapides lorsque j'ai mesuré). Dans le vrai cas, vous ne payez pratiquement aucun prix en performances pour cette seule ligne, donc je pense que cela vaut la peine d'être inclus. (De plus, dans la pratique, lorsque vous testez de nombreuses chaînes pour un bloc de départ spécifique, la plupart des comparaisons échouent car dans un cas typique, vous recherchez quelque chose.)
la source
startsWith("123", "0")
donnetrue
La
substr
fonction peut revenirfalse
dans de nombreux cas spéciaux, voici donc ma version, qui traite de ces problèmes:Tests (
true
signifie bon):En outre, la
substr_compare
fonction mérite également d'être examinée. http://www.php.net/manual/en/function.substr-compare.phpla source
Cela peut fonctionner
Source: https://stackoverflow.com/a/4419658
la source
Je le ferais comme ça
la source
Basé sur la réponse de James Black, voici ses extrémités avec la version:
Remarque: J'ai échangé la partie if-else pour la fonction startsWith de James Black, car strncasecmp est en fait la version insensible à la casse de strncmp.
la source
strrev()
c'est créatif mais très coûteux, surtout si vous avez des cordes à dire ... 100Kb.===
au lieu d'==
être sûr.0
est égal à beaucoup de choses en PHP.Pourquoi pas les suivants?
Production:
Gardez à l'esprit,
strpos
retournera faux si l'aiguille n'a pas été trouvée dans la botte de foin, et retournera 0 si, et seulement si, l'aiguille a été trouvée à l'index 0 (AKA au début).Et voici la fin Avec:
Dans ce scénario, il n'est pas nécessaire pour une fonction démarre avec () comme
retournera vrai ou faux avec précision.
Il semble étrange que ce soit aussi simple avec toutes les fonctions sauvages qui sévissent ici.
la source
strpos()
sera lente sauf lorsqu'elle correspond.strncmp()
serait beaucoup mieux dans ce cas.Bon nombre des réponses précédentes fonctionneront tout aussi bien. Cependant, c'est peut-être aussi court que vous pouvez le faire et lui faire faire ce que vous désirez. Vous déclarez simplement que vous aimeriez qu'il «revienne vrai». J'ai donc inclus des solutions qui renvoient booléen true / false et le textuel true / false.
la source
'true'
et'false'
sous forme de chaînes, qui sont toutes deuxtrue
dans un sens booléen. C'est un bon modèle pour quelque chose comme underhanded.xcott.com cependant;)Vous pouvez également utiliser des expressions régulières:
la source
preg_quote($needle, '/')
.Pas de copie et pas de boucle interne:
la source
Voici une solution efficace pour PHP 4. Vous pouvez obtenir des résultats plus rapides si vous utilisez PHP 5 à la
substr_compare
place destrcasecmp(substr(...))
.la source
Vous pouvez utiliser la fonction fnmatch pour cela.
la source