3

I am trying to figure out the most efficient way of looping through a string and finding all indexes of a certain letter.

I have used $word_or_phrase.indexOf( $letter ); to find a single index of a letter, but the letter is in $word_or_phrase multiple times. Would the most efficient way to do this be to build an array of all the indexes until .indexOf returns -1? Or how would you suggest me finding all the the indexes?

I have already taken time and found this: Javascript str.search() multiple instances

This works, but to me doesn't seem efficient when dealing with more than 2 indexes. What if I had 10?

Thanks for the advice in advance!

Community
  • 1
  • 1
Cory
  • 135
  • 1
  • 2
  • 11
  • Thank you to everyone for you quick and helpful suggestions. There was more than enough contribution to answer this question and this post should definitely help someone in the future. – Cory Jun 03 '13 at 14:57

5 Answers5

5

As the answer in the StackOverflow link you posted shows, you can use the second parameter of indexOf to define where the search starts in the string. You can continue looping over the string, using this technique, to get the indexes of all matched substrings:

function getMatchIndexes(str, toMatch) {
    var toMatchLength = toMatch.length,
        indexMatches = [], match,
        i = 0;

    while ((match = str.indexOf(toMatch, i)) > -1) {
        indexMatches.push(match);
        i = match + toMatchLength;
    }

    return indexMatches;
}

console.log(getMatchIndexes("asdf asdf asdf", "as"));

DEMO: http://jsfiddle.net/qxERV/

Another option is to use a regular expression to find all matches:

function getMatchIndexes(str, toMatch) {
    var re = new RegExp(toMatch, "g"),
        indexMatches = [], match;

    while (match = re.exec(str)) {
        indexMatches.push(match.index);
    }

    return indexMatches;
}

console.log(getMatchIndexes("asdf asdf asdf", "as"));

DEMO: http://jsfiddle.net/UCpeY/

And yet another option is to manually loop through the string's characters and compare to the target:

function getMatchIndexes(str, toMatch) {
    var re = new RegExp(toMatch, "g"),
        toMatchLength = toMatch.length,
        indexMatches = [], match,
        i, j, cur;

    for (i = 0, j = str.length; i < j; i++) {
        if (str.substr(i, toMatchLength) === toMatch) {
            indexMatches.push(i);
        }
    }

    return indexMatches;
}

console.log(getMatchIndexes("asdf asdf asdf", "as"));

DEMO: http://jsfiddle.net/KfJ9H/

Ian
  • 50,146
  • 13
  • 101
  • 111
2

Could be a solution:

http://jsfiddle.net/HkbpY/

var str = 'some kind of text with letter e in it',
    letter = 'e',
    indexes = [];

$.each(str.split(''),function(i,v){
    if(v === letter) indexes.push(i);
});

console.log(indexes);
A. Wolff
  • 74,033
  • 9
  • 94
  • 155
1

check this ...

var data = 'asd 111 asd 222 asd 333';
var count = countOccurence('asd', data);
console.info(count);
function countOccurence(item, data, count){
    if (count == undefined) { count = 0; }
    if (data.indexOf(item) != -1)
    {
        count = count+1;
        data = data.substring(data.indexOf(item) + item.length);
        count = countOccurence(item, data, count);
    }
    return count;
}
Bilal Murtaza
  • 785
  • 4
  • 9
0
var mystring = 'hello world';
var letterToCount = 'l';

var indexes = [];
for(var i=0; i<mystring.length; i++) {
    if(mystring[i] == letterToCount)
       indexes.push(i); 
}

alert(indexes.join(',')); //2,3,9
sjkm
  • 3,887
  • 2
  • 25
  • 43
  • Thanks sjkm for the quick response, however, this doesn't give the indexes, but gives me how many times the letter exists. In your example what I would want the output to be is occurrances = 3,4,9. I did not down-vote you for the record. – Cory Jun 03 '13 at 13:38
  • Please execute the code above... it returns exactly what you want^^ – sjkm Jun 03 '13 at 13:40
0

Try like this

var str = "foodfoodfoodfooooodfooooooood";
for (var index = str.indexOf("o");index > 0; index = str.indexOf("o", index+1)){
console.log(index);
}

See Demo

Dineshkani
  • 2,899
  • 7
  • 31
  • 43