En javascript, ¿hay un equivalente de String.indexOf () que toma una expresión regular en lugar de una cadena para el primer primer parámetro mientras permite un segundo parámetro?
Necesito hacer algo como
str.indexOf(/[abc]/ , i);
y
str.lastIndexOf(/[abc]/ , i);
Si bien String.search () toma una expresión regular como parámetro, ¡no me permite especificar un segundo argumento!
Editar:
Esto resultó ser más difícil de lo que pensaba originalmente, así que escribí una pequeña función de prueba para probar todas las soluciones proporcionadas ... se supone que regexIndexOf y regexLastIndexOf se han agregado al objeto String.
function test (str) {
var i = str.length +2;
while (i--) {
if (str.indexOf('a',i) != str.regexIndexOf(/a/,i))
alert (['failed regexIndexOf ' , str,i , str.indexOf('a',i) , str.regexIndexOf(/a/,i)]) ;
if (str.lastIndexOf('a',i) != str.regexLastIndexOf(/a/,i) )
alert (['failed regexLastIndexOf ' , str,i,str.lastIndexOf('a',i) , str.regexLastIndexOf(/a/,i)]) ;
}
}
y estoy probando lo siguiente para asegurarme de que al menos para una expresión regular de caracteres, el resultado es el mismo que si usáramos indexOf
// Busque la
prueba a entre las xes ('xxx');
prueba ('axx');
prueba ('xax');
prueba ('xxa');
prueba ('axa');
prueba ('xaa');
prueba ('aax');
prueba ('aaa');
fuente
|
por dentro[ ]
coincide con el carácter literal|
. Probablemente quisiste decir[abc]
.Respuestas:
Combinando algunos de los enfoques ya mencionados (el indexOf es obviamente bastante simple), creo que estas son las funciones que harán el truco:
Obviamente, modificar el objeto String incorporado enviaría señales de alerta para la mayoría de las personas, pero esto puede ser una vez cuando no es tan importante; simplemente se consciente de ello.
ACTUALIZACIÓN: Editado
regexLastIndexOf()
para que parezca imitarlastIndexOf()
ahora. Avíseme si aún falla y en qué circunstancias.ACTUALIZACIÓN: Pasa todas las pruebas que se encuentran en los comentarios de esta página y en la mía. Por supuesto, eso no significa que sea a prueba de balas. Cualquier comentario apreciado.
fuente
regexLastIndexOf
voluntad sólo se devuelve el índice del último no se solapan partido.regex.lastIndex = result.index + 1;
lugar deregex.lastIndex = ++nextStop;
. Se procederá al próximo partido mucho más rápido con suerte sin perder ningún resultado.Las instancias del
String
constructor tienen un.search()
método que acepta un RegExp y devuelve el índice de la primera coincidencia.Para comenzar la búsqueda desde una posición particular (falsificando el segundo parámetro de
.indexOf()
) puedeslice
desactivar los primerosi
caracteres:Pero esto obtendrá el índice en la cadena más corta (después de que se cortó la primera parte), por lo que querrá agregar la longitud de la parte cortada (
i
) al índice devuelto si no fue así-1
. Esto le dará el índice en la cadena original:fuente
function regexIndexOf(text, offset) { var initial = text.substr(offset).search(/re/); if(initial >= 0) { initial += offset; } return initial; }
Tengo una versión corta para ti. ¡Funciona bien para mí!
Y si quieres una versión prototipo:
EDITAR : si desea agregar soporte para fromIndex
Para usarlo, tan simple como esto:
fuente
startIndex
parámetro como de costumbreindeoxOf
ylastIndexOf
hacerlo.startIndex
(ofromIndex
). ¡Espero eso ayude!lastIndexOfRegex
también debe agregar de nuevo el valor defromIndex
al resultado."aRomeo Romeo".indexOfRegex(new RegExp("\\bromeo", 'gi'));
El resultado será 1 cuando debería ser 7, porque indexOf buscará por primera vez el "romeo", sin importar si está al principio de una palabra o no.Utilizar:
Vea la documentación aquí.
fuente
0
, y fue publicado ... siete años después.Basado en la respuesta de BaileyP. La principal diferencia es que estos métodos regresan
-1
si el patrón no puede coincidir.Editar: Gracias a la respuesta de Jason Bunting, tengo una idea. ¿Por qué no modificar la
.lastIndex
propiedad de la expresión regular? Aunque esto solo funcionará para patrones con la bandera global (/g
).Editar: actualizado para pasar los casos de prueba.
fuente
Podrías usar substr.
fuente
RexExp
las instancias ya tienen una propiedad lastIndex (si son globales) y, por lo tanto, lo que estoy haciendo es copiar la expresión regular, modificarla ligeramente para adaptarla a nuestros propósitos,exec
colocarla en la cadena y mirar ellastIndex
. Esto inevitablemente será más rápido que hacer un bucle en la cadena. (Tienes suficientes ejemplos de cómo poner esto en el prototipo de cuerda, ¿verdad?)También puede crear prototipos de las funciones en el objeto RegExp:
Una explicación rápida de cómo estoy modificando el
RegExp
: PorqueindexOf
solo tengo que asegurarme de que el indicador global esté configurado. PorquelastIndexOf
estoy usando una anticipación negativa para encontrar la última ocurrencia a menos queRegExp
ya coincida al final de la cadena.fuente
No lo hace de forma nativa, pero ciertamente puede agregar esta funcionalidad
No probé completamente estos métodos, pero parecen funcionar hasta ahora.
fuente
Después de que todas las soluciones propuestas fallaran mis pruebas de una forma u otra, (editar: algunas se actualizaron para pasar las pruebas después de que escribí esto) encontré la implementación de Mozilla para Array.indexOf y Array.lastIndexOf
Los usé para implementar mi versión de String.prototype.regexIndexOf y String.prototype.regexLastIndexOf de la siguiente manera:
Parecen pasar las funciones de prueba que proporcioné en la pregunta.
Obviamente, solo funcionan si la expresión regular coincide con un carácter, pero eso es suficiente para mi propósito, ya que lo usaré para cosas como ([abc], \ s, \ W, \ D)
Seguiré monitoreando la pregunta en caso de que alguien proporcione una implementación mejor / más rápida / más limpia / más genérica que funcione en cualquier expresión regular.
fuente
Necesitaba una
regexIndexOf
función también para una matriz, así que la programé yo mismo. Sin embargo, dudo que esté optimizado, pero supongo que debería funcionar correctamente.fuente
En ciertos casos simples, puede simplificar su búsqueda hacia atrás utilizando la división.
Esto tiene algunos problemas serios:
Pero en el lado positivo, es mucho menos código. Para una expresión regular de longitud constante que no puede superponerse (como
/\s\w/
para encontrar límites de palabras), esto es lo suficientemente bueno.fuente
Para datos con coincidencias dispersas, usar string.search es el más rápido en todos los navegadores. Se vuelve a cortar una cadena cada iteración para:
Para datos densos hice esto. Es complejo en comparación con el método de ejecución, pero para datos densos, es 2-10 veces más rápido que cualquier otro método que probé, y aproximadamente 100 veces más rápido que la solución aceptada. Los puntos principales son:
Se ejecuta la nueva expresión regular y se devuelven los resultados de ese ejecutivo o del primer ejecutivo;
jsPerf de métodos
No entiendo el propósito de las pruebas en la parte superior. Las situaciones que requieren una expresión regular son imposibles de comparar con una llamada a indexOf, que creo que es el punto de hacer el método en primer lugar. Para que la prueba pase, tiene más sentido usar 'xxx + (?! x)', que ajustar la forma en que itera la expresión regular.
fuente
El último índice de Jason Bunting no funciona. El mío no es óptimo, pero funciona.
fuente
Todavía no hay métodos nativos que realicen la tarea solicitada.
Aquí está el código que estoy usando. Imita el comportamiento de los métodos String.prototype.indexOf y String.prototype.lastIndexOf , pero también aceptan un RegExp como argumento de búsqueda además de una cadena que representa el valor a buscar.
Sí, la respuesta es bastante larga, ya que trata de seguir los estándares actuales lo más cerca posible y, por supuesto, contiene una cantidad razonable de comentarios de JSDOC . Sin embargo, una vez minimizado, el código tiene solo 2.27k y una vez comprimido para la transmisión, solo tiene 1023 bytes.
Los 2 métodos a los que esto se suma
String.prototype
(usando Object.defineProperty donde esté disponible) son:searchOf
searchLastOf
Pasa todas las pruebas que publicó el OP y, además, he probado las rutinas bastante a fondo en mi uso diario, y he tratado de asegurarme de que funcionen en múltiples entornos, pero los comentarios / problemas siempre son bienvenidos.
fuente
Si está buscando una búsqueda lastIndex muy simple con RegExp y no le importa si imita lastIndexOf hasta el último detalle, esto puede llamar su atención.
Simplemente invierto la cadena y resta el primer índice de ocurrencia de la longitud - 1. Resulta que pasa mi prueba, pero creo que podría surgir un problema de rendimiento con cadenas largas.
fuente
Utilicé lo
String.prototype.match(regex)
que devuelve una matriz de cadenas de todas las coincidencias encontradas de las dadasregex
en la cadena (más información, vea aquí ):fuente
Use expresiones regulares estándar:
fuente
Bueno, como solo buscas igualar la posición de un personaje , la expresión regular es posiblemente exagerada.
Supongo que todo lo que quieres es, en lugar de "encontrar primero a este personaje", solo encontrar el primero de estos personajes.
Por supuesto, esta es la respuesta simple, pero hace lo que su pregunta se propone hacer, aunque sin la parte de expresiones regulares (porque no aclaró por qué específicamente tenía que ser una expresión regular)
fuente