Como posso escrever duas funções que pegam uma string e retornam se ela começa com o caractere / string especificado ou termina com ela?
Por exemplo:
$str = '|apples}';
echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
s($str)->startsWith('|')
es($str)->endsWith('}')
útil, conforme encontrado nesta biblioteca autônoma .Respostas:
Use isso se você não quiser usar uma regex.
fonte
$length
não é necessário na última linha doendsWith()
.return substr($haystack, -strlen($needle))===$needle;
if
por completo, passando$length
como o terceiro parâmetro parasubstr
:return (substr($haystack, -$length, $length);
. Isso lida com o caso$length == 0
retornando uma string vazia e não o todo$haystack
.Você pode usar a
substr_compare
função para verificar o início e o término com:Essa deve ser uma das soluções mais rápidas do PHP 7 ( script de benchmark ). Testado em palheiros de 8 KB, agulhas de vários comprimentos e maletas cheias, parciais e sem correspondência.
strncmp
é um toque mais rápido para começar, mas não pode verificar as pontas.fonte
strrpos
qual (deveria) falhar imediatamente se a agulha não coincidir com o início do palheiro.-strlength($haystack)
) e pesquisando para trás a partir daí? Isso não significa que você não está procurando nada? Eu também não entendo as!== false
partes disso. Eu estou supondo que isso depende de uma peculiaridade do PHP, onde alguns valores são "verdadeiros" e outros "falsos", mas como isso funciona nesse caso?xxxyyy
agulha =yyy
e o usostrrpos
da pesquisa começa desde o iníciox
. Agora não temos uma correspondência bem-sucedida aqui (encontrado x em vez de y) e não podemos mais voltar atrás (estamos no início da string), a pesquisa falha imediatamente . Sobre o uso!== false
-strrpos
no exemplo acima, retornará 0 ou false e não outro valor. Da mesma forma,strpos
no exemplo acima, pode retornar$temp
(a posição esperada) ou falsa. Eu fui com!== false
a consistência, mas você poderia usar=== 0
e=== $temp
nas funções, respectivamente.Atualizado 23 de agosto de 2016
Funções
Testes
Resultados (PHP 7.0.9)
(Classificado da mais rápida para a mais lenta)
Resultados (PHP 5.3.29)
(Classificado da mais rápida para a mais lenta)
beginwith_benchmark.php
fonte
function startswith5b($haystack, $needle) {return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;}
adicionei uma resposta abaixo.Todas as respostas até agora parecem fazer um monte de trabalho desnecessário,
strlen calculations
,string allocations (substr)
, etc. A'strpos'
e'stripos'
funções retornam o índice da primeira ocorrência$needle
em$haystack
:fonte
endsWith()
função tem um erro. Sua primeira linha deve ser (sem o -1):$expectedPosition = strlen($haystack) - strlen($needle);
strpos($haystack, "$needle", 0)
se houvesse alguma chance de ela ainda não ser uma corda (por exemplo, se é provenientejson_decode()
). Caso contrário, o comportamento padrão [ímpar] destrpos()
pode causar resultados inesperados: " Se a agulha não for uma sequência, ela será convertida em um número inteiro e aplicada como o valor ordinal de um caractere. "Crédito para :
Verifique se uma string termina com outra string
Verifique se uma sequência começa com outra sequência
fonte
O regex funciona acima, mas com os outros ajustes também sugeridos acima:
fonte
Essa pergunta já tem muitas respostas, mas em alguns casos você pode se contentar com algo mais simples do que todas elas. Se a sequência que você procura for conhecida (codificada), você poderá usar expressões regulares sem citar etc.
Verifique se uma sequência começa com 'ABC':
termina com 'ABC':
No meu caso simples, eu queria verificar se uma string termina com barra:
A vantagem: como é muito curto e simples, você não precisa definir uma função (como
endsWith()
) como mostrado acima.Mas, novamente - isso não é uma solução para todos os casos, apenas esse muito específico.
fonte
@
, para que a barra (/
) não precise ser escapada. Veja o Exemplo 3 aqui: php.net/manual/en/function.preg-match.php .Se a velocidade é importante para você, tente isso (acredito que seja o método mais rápido)
Funciona apenas para strings e se $ haystack tiver apenas 1 caractere
fonte
endsWithChar('','x')
, mas o resultado está corretoAqui estão duas funções que não introduzem uma sequência temporária, que pode ser útil quando as agulhas são substancialmente grandes:
fonte
endsWidth
deve fazerreturn $needle==='' || substr_compare(
... por isso funciona como esperado para-strlen($needle)===0
que, sem a correção, fazendsWith('a','')
retornofalse
substr_compare()
verdade, então eu adicionei um PR a correção que :)endsWith('', 'foo')
dispara um aviso: “substr_compare (): a posição inicial não pode exceder o comprimento inicial da string”. Talvez esse seja outro problemasubstr_compare()
, mas, para evitá-lo, você precisa de uma verificação prévia como ...|| (strlen($needle) <= strlen($haystack) && substr_compare(
...) === 0);
return $needle === '' || @substr_compare(
.. para suprimir esse aviso.Solução mais rápida de extremidades com ():
Referência:
Resultados de referência:
fonte
Sei que isso foi concluído, mas você pode olhar para o strncmp, pois ele permite comparar o comprimento da string, portanto:
fonte
Você pode usar
strpos
estrrpos
fonte
strpos($sHaystack, $sNeedle) == 0
como estestrpos($sHaystack, $sNeedle) === 0
? Eu vejo um bug, quandofalse == 0
avalia paratrue
.Aqui está uma versão segura de vários bytes da resposta aceita, ela funciona bem para cadeias UTF-8:
fonte
startsWith
que deveria ser$length = mb_strlen($needle, 'UTF-8');
Linhas de linha curtas e fáceis de entender, sem expressões regulares.
começa com () é simples.
endsWith () usa o strrev () levemente sofisticado e lento:
fonte
Focalizando o startwith, se você tiver certeza de que as strings não estão vazias, adicionar um teste no primeiro caractere, antes da comparação, do strlen etc., acelera um pouco as coisas:
É de alguma forma (20% -30%) mais rápido. Adicionar outro teste de char, como $ haystack {1} === $ needle {1}, não parece acelerar muito as coisas, pode até diminuir a velocidade.
===
parece mais rápido que o==
operador condicional(a)?b:c
parece mais rápido queif(a) b; else c;
Para aqueles que perguntam "por que não usar strpos?" chamar outras soluções de "trabalho desnecessário"
O strpos é rápido, mas não é a ferramenta certa para este trabalho.
Para entender, aqui está uma pequena simulação como exemplo:
O que o computador faz "dentro"?
Supondo que strlen não itere toda a string (mas mesmo nesse caso) isso não é conveniente.
fonte
Espero que a resposta abaixo seja eficiente e também simples:
fonte
Normalmente, acabo indo a uma biblioteca como o underscore-php atualmente.
A biblioteca está cheia de outras funções úteis.
fonte
A resposta da mpen é incrivelmente completa, mas, infelizmente, o benchmark fornecido tem uma supervisão muito importante e prejudicial.
Como cada byte em agulhas e palheiros é completamente aleatório, a probabilidade de um par de agulha e palheiro diferir no primeiro byte é de 99,609375%, o que significa que, em média, cerca de 99609 dos 100000 pares diferem no primeiro byte . Em outras palavras, a referência é fortemente influenciada por
startswith
implementações que verificam o primeiro byte explicitamente, assim comostrncmp_startswith2
.Se o loop de geração de teste for implementado da seguinte maneira:
os resultados do benchmark contam uma história um pouco diferente:
Obviamente, essa referência ainda pode não ser perfeitamente imparcial, mas testa a eficiência dos algoritmos quando também são fornecidas agulhas parcialmente correspondentes.
fonte
em resumo:
fonte
Apenas uma recomendação:
Essa linha extra, comparando o primeiro caractere das seqüências, pode fazer com que o caso falso retorne imediatamente , tornando muitas das suas comparações muito mais rápidas (7x mais rápidas quando eu medi). No caso real, você não paga praticamente nenhum preço em desempenho por essa linha única, então acho que vale a pena incluir. (Além disso, na prática, quando você testa muitas seqüências de caracteres para um pedaço inicial específico, a maioria das comparações falha desde que, em um caso típico, você está procurando algo.)
fonte
startsWith("123", "0")
givestrue
A
substr
função pode retornarfalse
em muitos casos especiais, então aqui está minha versão, que lida com esses problemas:Testes (
true
significa bom):Além disso, a
substr_compare
função também vale a pena procurar. http://www.php.net/manual/en/function.substr-compare.phpfonte
Isso pode funcionar
Fonte: https://stackoverflow.com/a/4419658
fonte
Eu faria assim
fonte
Baseado na resposta de James Black, aqui estão os seus fins
Nota: Troquei a parte if-else pela função startWith de James Black, porque strncasecmp é realmente a versão que diferencia maiúsculas de minúsculas do strncmp.
fonte
strrev()
é criativo, mas muito caro, especialmente se você tiver seqüências de digamos ... 100 KB.===
vez de==
ter certeza.0
é igual a muitas coisas em PHP.Por que não o seguinte?
Resultado:
Lembre-se de
strpos
que retornará falso se a agulha não foi encontrada no palheiro e retornará 0 se, e somente se, a agulha foi encontrada no índice 0 (AKA no início).E aqui termina:
Nesse cenário, não há necessidade de uma função beginWith () como
retornará verdadeiro ou falso com precisão.
Parece estranho que seja simples assim, com todas as funções selvagens rodando desenfreadas aqui.
fonte
strpos()
será lento, exceto quando corresponder.strncmp()
seria muito melhor neste caso.Muitas das respostas anteriores funcionarão igualmente. No entanto, isso é possivelmente o mais curto possível e você pode fazer o que deseja. Você acabou de declarar que deseja "retornar verdadeiro". Portanto, incluí soluções que retornam booleano true / false e textual true / false.
fonte
'true'
e'false'
como strings, que são ambostrue
no sentido booleano. No entanto, é um bom padrão para algo como underhanded.xcott.com ;)Você também pode usar expressões regulares:
fonte
preg_quote($needle, '/')
.Sem cópia e sem loop interno:
fonte
Aqui está uma solução eficiente para o PHP 4. Você pode obter resultados mais rápidos se estiver usando o PHP 5 em
substr_compare
vez destrcasecmp(substr(...))
.fonte
Você pode usar a função fnmatch para isso.
fonte