2010-08-04 22 views
56

Estoy tratando de encontrar las posiciones de todas las ocurrencias de una cadena en otra cadena, no distingue entre mayúsculas y minúsculas.¿Cómo encontrar índices de todas las ocurrencias de una cadena en otra en JavaScript?

Por ejemplo, dada la cadena:

I learned to play the Ukulele in Lebanon.

y la cadena de búsqueda le, quiero obtener la matriz:

[2, 25, 27, 33] 

Ambas cadenas serán las variables - es decir, no puedo codifica sus valores

Pensé que era una tarea fácil para las expresiones regulares, pero después de luchar por un tiempo para encontrar una que funcionara, no tuve suerte.

Encontré this example de cómo lograr esto usando .indexOf(), pero seguramente tiene que haber una manera más concisa de hacerlo?

+2

+1 para la referencia de Líbano. – astazed

Respuesta

102
var str = "I learned to play the Ukulele in Lebanon." 
var regex = /le/gi, result, indices = []; 
while ((result = regex.exec(str))) { 
    indices.push(result.index); 
} 

ACTUALIZACIÓN

que no pudieron detectar en la pregunta original que la cadena de búsqueda debe ser una variable. He escrito otra versión para tratar este caso que usa indexOf, por lo que vuelve al punto de partida. Como señaló Wrikken en los comentarios, para hacer esto para el caso general con expresiones regulares, necesitaría escapar caracteres especiales de expresiones regulares, en cuyo punto creo que la solución de expresiones regulares se convierte en un dolor de cabeza más de lo que vale.

function getIndicesOf(searchStr, str, caseSensitive) { 
 
    var searchStrLen = searchStr.length; 
 
    if (searchStrLen == 0) { 
 
     return []; 
 
    } 
 
    var startIndex = 0, index, indices = []; 
 
    if (!caseSensitive) { 
 
     str = str.toLowerCase(); 
 
     searchStr = searchStr.toLowerCase(); 
 
    } 
 
    while ((index = str.indexOf(searchStr, startIndex)) > -1) { 
 
     indices.push(index); 
 
     startIndex = index + searchStrLen; 
 
    } 
 
    return indices; 
 
} 
 

 
var indices = getIndicesOf("le", "I learned to play the Ukulele in Lebanon."); 
 

 
document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>

+0

¿Cómo 'le' sería una cadena variable aquí? Incluso cuando se usa 'new Regexp (str);' el peligro de caracteres especiales es acecho, buscando '$ 2.50' por ejemplo. Algo así como 'regex = new Regexp (dynamicstring.replace (/ ([\\. + *? \\ [^ \\] $() {} =! <> |:])/G, '\\ $ 1'); 'sería más cercano en mi humilde opinión. No estoy seguro de si js tiene incorporado un mecanismo de escape de expresiones regulares. – Wrikken

+0

'nuevo RegExp (searchStr)' sería el camino, y sí, en el caso general, tendría que escapar de caracteres especiales. Realmente no vale la pena hacerlo a menos que necesite ese nivel de generalidad. –

+0

... ah, ya veo: no pude detectar en la pregunta que el OP necesita ese nivel de generalidad. Reescribiendo ... –

10
 
function indexes(source, find) { 
    var result = []; 
    for (i = 0; i < source.length; ++i) { 
    // If you want to search case insensitive use 
    // if (source.substring(i, i + find.length).toLowerCase() == find) { 
    if (source.substring(i, i + find.length) == find) { 
     result.push(i); 
    } 
    } 
    return result; 
} 

indexes("I learned to play the Ukulele in Lebanon.", "le") 

+2

+1 para una solución sin RegEx. – chryss

+0

Gracias, jcubic: parece una buena solución. – Bungle

+4

+1. Ejecuté algunas pruebas para compararlas con una solución usando Regex. El método más rápido fue el que usa Regex: http://jsperf.com/javascript-find-all – StuR

8

¡Seguro que puede hacer esto!

//make a regular expression out of your needle 
var needle = 'le' 
var re = new RegExp(needle,'gi'); 
var haystack = 'I learned to play the Ukulele'; 

var results = new Array();//this is the results you want 
while (re.exec(haystack)){ 
    results.push(re.lastIndex); 
} 

Editar: aprender a deletrear RegExp

Además, me di cuenta de que esto no es exactamente lo que quiere, como lastIndex nos dice al final de no la aguja al principio, pero está cerca - usted podría empujar re.lastIndex-needle.length en la matriz de resultados ...

Editar: añadir enlace

La respuesta de @Tim Down usa el objeto de resultados de RegExp.exec(), y todos mis recursos Javascript pasan por alto su uso (además de darle la cadena coincidente). Entonces, cuando usa result.index, ese es un tipo de Objeto coincidente sin nombre. En el MDC description of exec, en realidad describen este objeto con detalles decentes.

+0

Annnd @Tim Down tiene el ganador, ignórame ... – Ryley

+0

¡Ja! Gracias por contribuir, en cualquier caso, ¡lo aprecio! – Bungle

-1
function countInString(searchFor,searchIn){ 

var results=0; 
var a=searchIn.indexOf(searchFor) 

while(a!=-1){ 
    searchIn=searchIn.slice(a*1+searchFor.length); 
    results++; 
    a=searchIn.indexOf(searchFor); 
} 

return results; 

} 
-1

el código de abajo va a hacer el trabajo para usted:

function indexes(source, find) { 
    var result = []; 
    for(i=0;i<str.length; ++i) { 
    // If you want to search case insensitive use 
    // if (source.substring(i, i + find.length).toLowerCase() == find) { 
    if (source.substring(i, i + find.length) == find) { 
     result.push(i); 
    } 
    } 
    return result; 
} 

indexes("hello, how are you", "ar") 
3

Uso String.prototype.match.

Aquí se muestra un ejemplo de la propia documentación MDN:

var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 
var regexp = /[A-E]/gi; 
var matches_array = str.match(regexp); 

console.log(matches_array); 
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e'] 
+0

Esto es bastante sencillo. – igaurav

+4

La pregunta es cómo encontrar * índices * de ocurrencias, ¡no ocurrencias! – Luckylooke

1

Si lo que desea es encontrar la posición de todos los partidos que me gustaría apuntar a un pequeño truco:

haystack = 'I learned to play the Ukulele in Lebanon.' 
needle = 'le' 
splitOnFound = haystack.split(needle).map(function (culm) { 
    return this.pos += culm.length + needle.length 
}, {pos: -needle.length}).slice(0, -1) 

puede no ser aplicable si tiene un RegExp con longitud variable, pero para algunos podría ser útil.

Cuestiones relacionadas