2010-08-04 8 views
56

Ich versuche, die Positionen aller Vorkommen einer Zeichenfolge in einer anderen Zeichenfolge zu finden, Groß-und Kleinschreibung.Wie findet man Indizes von allen Vorkommen einer Zeichenfolge in einer anderen in JavaScript?

Zum Beispiel angesichts der string:

I learned to play the Ukulele in Lebanon.

und der Suchbegriff le, möchte ich das Array erhalten:

[2, 25, 27, 33] 

Beide Strings Variablen sein - das heißt, ich kann nicht Hard-Code ihre Werte.

Ich dachte, dass dies eine einfache Aufgabe für reguläre Ausdrücke war, aber nachdem ich mich eine Weile bemüht hatte, eine zu finden, die funktionieren würde, hatte ich kein Glück.

Ich habe this example gefunden, wie man dies unter Verwendung .indexOf() erreicht, aber sicher muss es einen prägnanteren Weg geben, es zu tun?

+2

+1 für Libanon Referenz. – astazed

Antwort

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); 
} 

UPDATE

ich nicht in der ursprünglichen Frage zu erkennen, dass der Suchbegriff eine Variable sein muss. Ich habe eine andere Version geschrieben, die sich mit diesem Fall befasst, der indexOf verwendet, so dass Sie zurück sind, wo Sie angefangen haben. Wie Wrikken in den Kommentaren darauf hingewiesen hat, müßten Sie für den allgemeinen Fall mit regulären Ausdrücken speziellen Regex-Zeichen entkommen. An diesem Punkt wird die Regex-Lösung mehr Kopfschmerzen als es wert ist.

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

Wie wäre 'le' eine variable Zeichenfolge hier? Auch bei der Verwendung von 'new Regexp (str);' lauert die Gefahr von Sonderzeichen, die beispielsweise nach $ 2,50 suchen. So etwas wie 'regex = new Regexp (dynamikstring.replace (/ ([\\. + *? \\ [^ \\] $() {} =! <> |:])/G, '\\ $ 1')); 'wäre näher dran IMHO. Ich bin mir nicht sicher, ob js einen eingebauten Regex-Escaping-Mechanismus hat. – Wrikken

+0

'neue RegExp (searchStr)' wäre der Weg, und ja, im allgemeinen Fall müssten Sie Sonderzeichen zu entkommen. Es lohnt sich nicht wirklich, es sei denn, Sie brauchen diese Ebene der Allgemeinheit. –

+0

... ah, ich sehe: Ich habe es versäumt, in der Frage zu erkennen, dass das OP diese Ebene der Allgemeinheit braucht. Umschreiben ... –

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 für eine RegEx-freie Lösung. – chryss

+0

Danke, jcubic - das sieht nach einer guten Lösung aus. – Bungle

+4

+1. Ich habe einige Tests zum Vergleich mit einer Lösung mit Regex durchgeführt. Die schnellste Methode war die mit Regex: http://jsperf.com/javascript-find-all – StuR

8

Sie sicher, kann dies tun!

//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); 
} 

Edit: lernen RegExp zu buchstabieren

Auch ich erkannte dies nicht ist genau, was Sie wollen, wie lastIndex uns das Ende der Nadel sagt nicht der Anfang, aber es ist nah - Sie könnten re.lastIndex-needle.length in die Ergebnis-Reihe schieben ...

Edit: Hinzufügen Link

@Tim Downs Antwort verwendet das Ergebnisobjekt von RegExp.exec(), und alle meine Javascript-Ressourcen beschönigen seine Verwendung (abgesehen davon, dass Sie die passende Zeichenfolge erhalten). Wenn er also result.index verwendet, ist das eine Art unbenanntes Match-Objekt. In der MDC description of exec beschreiben sie tatsächlich dieses Objekt in anständigen Details.

+0

Annnd @Tim Down hat den Gewinner, ignoriere mich ... – Ryley

+0

Ha! Danke für den Beitrag, auf jeden Fall - ich weiß es zu schätzen! – 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

die folgenden Code wird die Arbeit für Sie tun:

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

Verwendung String.prototype.match.Hier

ist ein Beispiel aus der MDN-Dokumentation selbst:

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

Das ist ziemlich einfach. – igaurav

+4

Die Frage ist, wie man * Indizes * von Vorkommen findet, nicht selbst! – Luckylooke

1

Wenn Sie nur die Position aller Übereinstimmungen finden möchten Ich mag würde Sie zu einem kleinen Hack Punkt:

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) 

es möglicherweise nicht anwendbar, wenn Sie eine RegExp mit variabler Länge haben, aber für einige könnte es hilfreich sein.

Verwandte Themen