Estoy tratando de encontrar las posiciones de todas las ocurrencias de una cadena en otra cadena, sin distinción entre mayúsculas y minúsculas.
Por ejemplo, dada la cadena:
Aprendí a tocar el ukelele en el Líbano.
y la cadena de búsqueda le
, quiero obtener la matriz:
[2, 25, 27, 33]
Ambas cadenas serán variables, es decir, no puedo codificar sus valores.
Pensé que esta era una tarea fácil para las expresiones regulares, pero después de luchar durante un tiempo para encontrar una que funcionara, no tuve suerte.
Encontré este ejemplo de cómo lograr esto usando .indexOf()
, pero seguramente tiene que haber una forma más concisa de hacerlo.
fuente
le
una cadena variable aquí? Incluso cuandonew Regexp(str);
se acecha el peligro de los caracteres especiales, la búsqueda,$2.50
por ejemplo. Algo asíregex = new Regexp(dynamicstring.replace(/([\\.+*?\\[^\\]$(){}=!<>|:])/g, '\\$1'));
sería más cercano en mi humilde opinión. No estoy seguro de si js tiene un mecanismo de escape de expresiones regulares incorporado.new RegExp(searchStr)
sería el camino, y sí, en el caso general tendrías que escapar de los caracteres especiales. Realmente no vale la pena hacerlo a menos que necesite ese nivel de generalidad.searchStr=aaa
y esostr=aaaaaa
. Luego, en lugar de encontrar 4 ocurrencias, su código encontrará solo 2 porque está haciendo saltossearchStr.length
en el bucle.Aquí está la versión gratuita de expresiones regulares:
EDITAR : y si desea hacer coincidir cadenas como 'aaaa' y 'aa' para encontrar [0, 2] use esta versión:
fuente
var result = indexes('aaaa', 'aa')
? ¿El resultado esperado debería ser[0, 1, 2]
o[0, 2]
?i+=find.length;
y en elsei++
¡Seguro que puedes hacer esto!
Editar: aprende a deletrear RegExp
Además, me di cuenta de que esto no es exactamente lo que quieres, ya que
lastIndex
nos dice que el final de la aguja no es el principio, pero está cerca.re.lastIndex-needle.length
ingresar a la matriz de resultados ...Editar: agregar enlace
La respuesta de @Tim Down usa el objeto de resultados de RegExp.exec (), y todos mis recursos de Javascript pasan por alto su uso (además de darle la cadena coincidente). Entonces, cuando lo usa
result.index
, es una especie de Match Object sin nombre. En la descripción MDC de exec , en realidad describen este objeto con un detalle decente.fuente
Un revestimiento usando
String.protype.matchAll
(ES2020):Usando sus valores:
Si le preocupa hacer una extensión y una
map()
en una línea, lo ejecuté con unfor...of
bucle para un millón de iteraciones (usando sus cadenas). El trazador de líneas tiene un promedio de 1420 ms, mientras que elfor...of
promedio de 1150 ms en mi máquina. Esa no es una diferencia insignificante, pero el delineador funcionará bien si solo estás haciendo un puñado de coincidencias.Ver
matchAll
en caniusefuente
Si solo desea encontrar la posición de todas las coincidencias, me gustaría señalarle un pequeño truco:
Puede que no se pueda aplicar si tiene una expresión regular con longitud variable, pero para algunos podría ser útil.
Esto distingue entre mayúsculas y minúsculas. Para la insensibilidad a mayúsculas y minúsculas, utilice la
String.toLowerCase
función antes.fuente
Aquí hay un código simple
fuente
Siga la respuesta de @jcubic, su solución causó una pequeña confusión en mi caso.Por
ejemplo
var result = indexes('aaaa', 'aa')
, volverá en[0, 1, 2]
lugar de.[0, 2]
Así que actualicé un poco su solución como se muestra a continuación para que coincida con mi caso.
fuente
Gracias por todas las respuestas. Los revisé todos y se me ocurrió una función que le da al primero un último índice de cada aparición de la subcadena 'aguja'. Lo estoy publicando aquí en caso de que ayude a alguien.
Tenga en cuenta que no es lo mismo que la solicitud original solo para el comienzo de cada aparición. Se adapta mejor a mi caso de uso porque no es necesario mantener la longitud de la aguja.
fuente
Verifique esta solución que también podrá encontrar la misma cadena de caracteres, avíseme si falta algo o no está bien.
fuente
fuente
el siguiente código hará el trabajo por usted:
fuente
Utilice String.prototype.match .
Aquí hay un ejemplo de los propios documentos de MDN:
fuente