Estou tentando encontrar as posições de todas as ocorrências de uma string em outra string, sem distinção entre maiúsculas e minúsculas.
Por exemplo, dada a string:
Aprendi a tocar Ukulele no Líbano.
e a string de pesquisa le
, desejo obter a matriz:
[2, 25, 27, 33]
Ambas as strings serão variáveis - ou seja, não posso codificar seus valores.
Achei que fosse uma tarefa fácil para expressões regulares, mas depois de lutar por um tempo para encontrar uma que funcionasse, não tive sorte.
Achei esse exemplo de como fazer isso usando .indexOf()
, mas com certeza tem que haver uma maneira mais concisa de fazer isso?
fonte
le
uma string variável aqui? Mesmo quando usandonew Regexp(str);
o perigo de caracteres especiais está à espreita, procurando$2.50
por exemplo. Algo comoregex = new Regexp(dynamicstring.replace(/([\\.+*?\\[^\\]$(){}=!<>|:])/g, '\\$1'));
seria IMHO mais perto. Não tenho certeza se js tem um mecanismo de escape regex integrado.new RegExp(searchStr)
seria o caminho, e sim, no caso geral você teria que escapar de caracteres especiais. Realmente não vale a pena fazer, a menos que você precise desse nível de generalidade.searchStr=aaa
e issostr=aaaaaa
. Então, em vez de encontrar 4 ocorrências, seu código encontrará apenas 2, porque você está pulandosearchStr.length
no loop.Aqui está a versão gratuita do regex:
EDITAR : e se você quiser combinar strings como 'aaaa' e 'aa' para encontrar [0, 2], use esta versão:
fonte
var result = indexes('aaaa', 'aa')
? O resultado esperado deve ser[0, 1, 2]
ou[0, 2]
?i+=find.length;
e em elsei++
Você com certeza pode fazer isso!
Editar: aprenda a soletrar RegExp
Além disso, percebi que isso não é exatamente o que você quer, pois
lastIndex
nos diz que o fim da agulha não é o começo, mas está perto - você pode empurrarre.lastIndex-needle.length
para a matriz de resultados ...Editar: adicionar link
A resposta de @Tim Down usa o objeto de resultados de RegExp.exec (), e todos os meus recursos Javascript encobrem seu uso (além de fornecer a string correspondente). Então, quando ele usa
result.index
, é algum tipo de Match Object sem nome. Na descrição de exec do MDC , eles realmente descrevem esse objeto com detalhes decentes.fonte
Um liner usando
String.protype.matchAll
(ES2020):Usando seus valores:
Se você está preocupado em fazer um spread e um
map()
em uma linha, executei com umfor...of
loop para um milhão de iterações (usando suas strings). O único liner tem uma média de 1420ms, enquanto asfor...of
médias de 1150ms na minha máquina. Essa não é uma diferença insignificante, mas o forro funcionará bem se você estiver fazendo apenas um punhado de fósforos.Veja
matchAll
no caniusefonte
Se você apenas deseja encontrar a posição de todas as correspondências, gostaria de apontar um pequeno hack:
Pode não ser aplicável se você tiver um RegExp com comprimento variável, mas para alguns pode ser útil.
Isso é sensível a maiúsculas e minúsculas. Para insensibilidade ao caso, use a
String.toLowerCase
função antes.fonte
Aqui está um código simples
fonte
Siga a resposta de @jcubic, a solução dele causou uma pequena confusão para o meu caso
Por exemplo
var result = indexes('aaaa', 'aa')
ele retornará ao[0, 1, 2]
invés de[0, 2]
Então eu atualizei um pouco a solução dele conforme abaixo para corresponder ao meu caso
fonte
Obrigado por todas as respostas. Passei por todos eles e descobri uma função que dá ao primeiro e ao último índice de cada ocorrência da substring 'agulha'. Estou postando aqui caso possa ajudar alguém.
Observe que não é o mesmo que a solicitação original apenas para o início de cada ocorrência. É mais adequado ao meu caso de uso porque você não precisa manter o comprimento da agulha.
fonte
Verifique esta solução que também conseguirá encontrar a mesma string de caracteres, diga-me se algo está faltando ou não está certo.
fonte
fonte
o código abaixo fará o trabalho por você:
fonte
Use String.prototype.match .
Aqui está um exemplo dos próprios documentos MDN:
fonte