J'essaie de trouver les positions de toutes les occurrences d'une chaîne dans une autre chaîne, insensible à la casse.
Par exemple, étant donné la chaîne:
J'ai appris à jouer du ukulélé au Liban.
et la chaîne de recherche le
, je veux obtenir le tableau:
[2, 25, 27, 33]
Les deux chaînes seront des variables - c'est-à-dire que je ne peux pas coder en dur leurs valeurs.
J'ai pensé que c'était une tâche facile pour les expressions régulières, mais après avoir lutté pendant un certain temps pour en trouver une qui fonctionnerait, je n'ai pas eu de chance.
J'ai trouvé cet exemple de la façon d'accomplir cela en utilisant .indexOf()
, mais il doit sûrement y avoir une façon plus concise de le faire?
la source
le
une chaîne variable ici? Même lorsque vous utiliseznew Regexp(str);
le danger des caractères spéciaux se cache, la recherche$2.50
par exemple. Quelque chose commeregex = new Regexp(dynamicstring.replace(/([\\.+*?\\[^\\]$(){}=!<>|:])/g, '\\$1'));
serait plus proche IMHO. Je ne sais pas si js a un mécanisme d'échappement regex intégré.new RegExp(searchStr)
serait le moyen, et oui, dans le cas général, il faudrait échapper aux caractères spéciaux. Cela ne vaut vraiment la peine que si vous avez besoin de ce niveau de généralité.searchStr=aaa
et celastr=aaaaaa
. Ensuite, au lieu de trouver 4 occurrences, votre code n'en trouvera que 2 parce que vous faites des sautssearchStr.length
dans la boucle.Voici la version gratuite de regex:
EDIT : et si vous voulez faire correspondre des chaînes comme 'aaaa' et 'aa' pour trouver [0, 2] utilisez cette version:
la source
var result = indexes('aaaa', 'aa')
? Le résultat attendu devrait être[0, 1, 2]
ou[0, 2]
?i+=find.length;
et dans elsei++
Vous pouvez certainement le faire!
Edit: apprenez à épeler RegExp
De plus, j'ai réalisé que ce n'était pas exactement ce que vous vouliez, comme
lastIndex
nous le dit la fin de l'aiguille, pas le début, mais c'est proche - vous pouvez pousserre.lastIndex-needle.length
dans le tableau des résultats ...Modifier: ajouter un lien
La réponse de @Tim Down utilise l'objet de résultats de RegExp.exec (), et toutes mes ressources Javascript passent sous silence son utilisation (en plus de vous donner la chaîne correspondante). Donc, quand il l'utilise
result.index
, c'est une sorte d'objet de correspondance sans nom. Dans la description MDC de exec , ils décrivent en fait cet objet avec des détails décents.la source
Une doublure utilisant
String.protype.matchAll
(ES2020):En utilisant vos valeurs:
Si vous craignez de faire un spread et un
map()
en une ligne, je l'ai exécuté avec unefor...of
boucle pour un million d'itérations (en utilisant vos chaînes). La seule doublure mesure en moyenne 1420 ms tandis que lafor...of
moyenne est de 1150 ms sur ma machine. Ce n'est pas une différence insignifiante, mais la seule doublure fonctionnera bien si vous ne faites que quelques matchs.Voir
matchAll
sur caniusela source
Si vous voulez juste trouver la position de tous les matchs, je voudrais vous indiquer un petit hack:
Cela peut ne pas être applicable si vous avez une RegExp avec une longueur variable, mais pour certains, cela peut être utile.
Ceci est sensible à la casse. Pour l'insensibilité à la casse, utilisez la
String.toLowerCase
fonction avant.la source
Voici un simple extrait de code:
la source
Suivez la réponse de @jcubic, sa solution a causé une petite confusion pour mon cas
Par exemple
var result = indexes('aaaa', 'aa')
il reviendra à la[0, 1, 2]
place de[0, 2]
Donc j'ai mis à jour un peu sa solution comme ci-dessous pour correspondre à mon cas
la source
Merci pour toutes vos réponses. Je les ai tous parcourus et j'ai trouvé une fonction qui donne au premier un dernier index de chaque occurrence de la sous-chaîne «aiguille». Je le poste ici au cas où cela aiderait quelqu'un.
Veuillez noter que ce n'est pas la même chose que la demande originale pour seulement le début de chaque occurrence. Cela convient mieux à mon cas d'utilisation car vous n'avez pas besoin de garder la longueur de l'aiguille.
la source
Vérifiez cette solution qui pourra également trouver la même chaîne de caractères, faites-moi savoir si quelque chose manque ou ne va pas.
la source
Voici ma solution sans regex.
la source
Je recommanderais la réponse de Tim. Cependant, @blazs déclare "Supposons searchStr = aaa et que str = aaaaaa. Ensuite, au lieu de trouver 4 occurrences, votre code n'en trouvera que 2 car vous faites des sauts par searchStr.length dans la boucle.", Ce qui est vrai en regardant Code de Tim, spécifiquement cette ligne ici: startIndex = index + searchStrLen; Le code de Tim ne serait pas en mesure de trouver une instance de la chaîne recherchée dans la longueur d'elle-même. Donc, j'ai modifié la réponse de Tim:
Le changer en "+ 1" au lieu de "+ searchStrLen" permettra à l'index 1 d'être dans le tableau des indices si j'ai une chaîne de "aaaa" et un searchStr de "aa".
Deuxième réponse
J'ai un autre extrait de code qui fonctionne également. Cela imite la réponse fournie par @YuJie, sauf que celle-ci est plus compacte que la réponse de Yu Jie:
Cependant, l'inconvénient de cet extrait de code est qu'il peut prendre un peu plus de temps que le premier, car le premier utilise la fonction intégrée JavaScript indexOf (), tandis que le second est un peu comme le vieil adage "re -inventer la roue. " Donc, dans l'ensemble, je recommanderais ma première réponse au lieu de celle-ci. PS Si quelqu'un souhaite des commentaires dans le code pour expliquer le fonctionnement du code, veuillez le dire, et je serai heureux de répondre à la demande.
la source
la source
le code ci-dessous fera le travail pour vous:
la source
Utilisez String.prototype.match .
Voici un exemple tiré de la documentation MDN elle-même:
la source