Sunfox

Le journal de Sunny Ripert


Startswith et Endswith en PHP

function startswith($hay, $needle) {
  return substr($hay, 0, strlen($needle)) === $needle;
}

function endswith($hay, $needle) {
  return substr($hay, -strlen($needle)) === $needle;
}

Articles probablement reliés

17 Commentaires

  1. 1 SphAx3D :

    Bon je suis pas expert, c’est sûr, mais j’ai pas trop compris le code ^^. Tu pourrais en dire un peu plus s’il te plait ? :-)

  2. 2 Sunny :

    Ces fonctions renvoient si oui ou non un texte commence (ou finit) par un autre. Autant dire des fonctions très utiles, d’ailleurs disponibles par défaut dans de nombreux autres langages.

    startswith() retourne vrai si l’aiguille est vide ou que l’aiguille est égale à la botte de foin ou enfin que la position de l’aiguille dans la botte de foin est 0.

    Même chose sur endswith() mais avec les deux textes inversés par la fonction strrev() :)

  3. 3 mat :

    Tu cherches à rivaliser avec les one-liners illisibles de perl ? :)

  4. 4 Sunny :

    Boah elle est pas très compliquée ! Juste assez courte pour ne pas être redondante. Et sachant que c’est du genre à être utilisée et recopiée très souvent il ne fallait pas qu’elle prenne trop de place.

    J’allais quand même pas faire :

    if ($needle === $hay or strpos($hay, $needle) === 0)
    	return true;
  5. 5 Pihtt :

    Clair et concis, c’est comme ça que je les aime.
    Merci.

  6. 6 Thoams :

    Bonsoir,

    après un rapide petit test, il semblerai que si $needle === $hay, alors strpos($hay, $needle) === 0.
    Si je ne me suis pas trompé, le premier test ne doit pas servir à grand chose !?

    Bonne soirée,
    Thoams ;-)

  7. 7 Sunny :

    En effet Thoams, je ne retrouve plus la logique qui m’a fait ajouter le premier test dans chaque… Peut-être une histoire de performances. Quoi qu’il en soit j’ai supprimé ces tests, suis revenu à une version plus simple.

  8. 8 Thoams :

    Bonjour Sunny,

    je suis content d’avoir servi à quelque chose :)
    En parlant de performance, je me demandait pourquoi tu n’avais pas utiliser :

    strpos($hay, $needle) === strlen($hay)-str($needle)

    au lieu de :

    strpos(strrev($hay), strrev($needle)) === 0

    Je me disais que strrev(), par rapport au strlen(), avait une complexité grandissante avec la taille des chaîne, non ?

  9. 9 Sunny :

    Thoams : je suis d’accord, je serais ravi de trouver une solution courte et élégante sans strrev(). Ton code, lui, renvoie faux pour des chaînes qui contiennent le texte autre part qu’à la fin :

    strpos('foofoo','foo') === strlen('foofoo')-strlen('foo') # => false

    Une autre proposition ? ;)

    PS : Je me suis permis de mettre en forme le code de tes commentaires.

  10. 10 Thoams :

    Salut,

    nickel pour la mise en forme ;-)
    Pour le fait que ça renvoi faux, je ne vois pas le problème. C’est comme pour startswith() qui renvoi faux pour des chaînes qui contiennent le texte autre part qu’au début ?

    Sinon, j’y ai repensé pendant la pause de midi, et ce qui me pose problème c’est le strpos(). En effet, cette méthode va chercher partout dans la string, alors qu’on ne veut parser que quelques caractères. Il y a donc une bonne partie du travail qui est fait inutilement.

    Je te propose ce code plutôt :

    function startswith($hay, $needle) {
        return substr($hay, 0, strlen($needle)) == $needle;
    }
    function endswith($hay, $needle) {
        return substr($hay, -strlen($needle)) == $needle;
    }

    le code est pas testé. Mais le principe que j’utiliserais est là.
    Faudrait aussi voir ce qui ce passe si quelqu’un s’amuse à entrer un $needle plus grand que $hay.

    Bonne après-midi,
    Thoams ;-)

  11. 11 Sunny :

    Pour le fait que ça renvoi faux, je ne vois pas le problème. C’est comme pour startswith() qui renvoi faux pour des chaînes qui contiennent le texte autre part qu’au début ?

    Ce que je voulais dire par là c’était que mon startswith() ne renvoie pas faux si le texte cherché est en double.

    J’aime bien ces versions avec substr(), d’après quelques petits tests elles fonctionnent bien. Je te les pique ;)

    Merci et bonne après-midi ! :)

  12. 12 Thoams :

    Ahhh… j’avais pas compris pour strpos(). On aurait du utiliser la fonction strrpos(), mais cette dernière n’est pas conseillée, car elle n’a pas le même fonctionnement sous PHP4 et PHP5.

    Pas de soucis pour substr(). Si tu les as testés, je vais les utiliser aussi !

    Bonne aprèm,
    Thoams ;-)

  13. 13 Tom :

    Maintenant y a ‘substr_compare’ !

  14. 14 Tom :

    A mon avis, la plus optimisée:

    static public function endsWith($hay,$needle)
    		{
    			$a = strlen($needle) - 1;
    			$i = strlen($hay) - 1;
    			
    			while ($i > 0)
    			{
    				if ($hay[$i] != $needle[$a])
    				{
    					return false;
    				}
    				
    				$i --;
    				$a --;
    				
    				if ($a == 0)
    				{
    					return true;
    				}
    			}
    			
    			return false;
    		}
  15. 15 Sunny :

    Mieux qu’un avis, un benchmark ?

  16. 16 Fred :

    Votre fonction ne fonctionne pas car il faut utiliser la triple égalité.
    Pour vous en convaincre, essayez avec ‘0’ et ‘000’ dans cet ordre :
    startswith('0', '000') ; // '0' ne commence pas par ‘000’ !

    Il faut donc écrire

    function startswith($hay, $needle) {
      return substr($hay, 0, strlen($needle)) === $needle;
    }

    Amusez-vous bien ;)

  17. 17 Sunny :

    Merci Fred !

Commenter


Vous pouvez avoir une jolie icône vous aussi en créant un gravatar.

Vous pouvez y saupoudrer de l'HTML5 avec les balises et suivantes : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>.


:D Sunny Ripert

est un développeur web vivant à Paris.

CV, me contacter


Textes et contenus sous licence Creative Commons.
Site crée par mes soins et propulsé par WordPress.