How to get the nth occurrence in a string?

Javascript

Javascript Problem Overview


I would like to get the starting position of the 2nd occurrence of ABC with something like this:

var string = "XYZ 123 ABC 456 ABC 789 ABC";
getPosition(string, 'ABC', 2) // --> 16

How would you do it?

Javascript Solutions


Solution 1 - Javascript

const string = "XYZ 123 ABC 456 ABC 789 ABC";

function getPosition(string, subString, index) {
  return string.split(subString, index).join(subString).length;
}

console.log(
  getPosition(string, 'ABC', 2) // --> 16
)

Solution 2 - Javascript

You can also use the string indexOf without creating any arrays.

The second parameter is the index to start looking for the next match.

function nthIndex(str, pat, n){
	var L= str.length, i= -1;
	while(n-- && i++<L){
		i= str.indexOf(pat, i);
        if (i < 0) break;
	}
	return i;
}

var s= "XYZ 123 ABC 456 ABC 789 ABC";

nthIndex(s,'ABC',3)

/*  returned value: (Number)
24
*/

Solution 3 - Javascript

Working off of kennebec's answer, I created a prototype function which will return -1 if the nth occurence is not found rather than 0.

String.prototype.nthIndexOf = function(pattern, n) {
    var i = -1;
    
    while (n-- && i++ < this.length) {
        i = this.indexOf(pattern, i);
        if (i < 0) break;
    }

    return i;
}

Solution 4 - Javascript

Because recursion is always the answer.

function getPosition(input, search, nth, curr, cnt) {
    curr = curr || 0;
    cnt = cnt || 0;
    var index = input.indexOf(search);
    if (curr === nth) {
        if (~index) {
            return cnt;
        }
        else {
            return -1;
        }
    }
    else {
        if (~index) {
            return getPosition(input.slice(index + search.length),
              search,
              nth,
              ++curr,
              cnt + index + search.length);
        }
        else {
            return -1;
        }
    }
}

Solution 5 - Javascript

Here's my solution, which just iterates over the string until n matches have been found:

String.prototype.nthIndexOf = function(searchElement, n, fromElement) {
    n = n || 0;
    fromElement = fromElement || 0;
    while (n > 0) {
        fromElement = this.indexOf(searchElement, fromElement);
        if (fromElement < 0) {
            return -1;
        }
        --n;
        ++fromElement;
    }
    return fromElement - 1;
};

var string = "XYZ 123 ABC 456 ABC 789 ABC";
console.log(string.nthIndexOf('ABC', 2));

>> 16

Solution 6 - Javascript

This method creates a function that calls for the index of nth occurrences stored in an array

function nthIndexOf(search, n) { 
    var myArray = []; 
    for(var i = 0; i < myString.length; i++) { //loop thru string to check for occurrences
	    if(myStr.slice(i, i + search.length) === search) { //if match found...
		    myArray.push(i); //store index of each occurrence			
	    }
    } 
	return myArray[n - 1]; //first occurrence stored in index 0 
}

Solution 7 - Javascript

Shorter way and I think easier, without creating unnecessary strings.

const findNthOccurence = (string, nth, char) => {
  let index = 0
  for (let i = 0; i < nth; i += 1) {
    if (index !== -1) index = string.indexOf(char, index + 1)
  }
  return index
}

Solution 8 - Javascript

Using indexOf and Recursion:

First check if the nth position passed is greater than the total number of substring occurrences. If passed, recursively go through each index until the nth one is found.

var getNthPosition = function(str, sub, n) {
    if (n > str.split(sub).length - 1) return -1;
	var recursePosition = function(n) {
        if (n === 0) return str.indexOf(sub);
        return str.indexOf(sub, recursePosition(n - 1) + 1);
    };
    return recursePosition(n);
};

Solution 9 - Javascript

Using String.indexOf:

var stringToMatch = "XYZ 123 ABC 456 ABC 789 ABC";

function yetAnotherGetNthOccurance(string, seek, occurance) {
    var index = 0, i = 1;

    while (index !== -1) {
        index = string.indexOf(seek, index + 1);
        if (occurance === i) {
           break;
        }
        i++;
    }
    if (index !== -1) {
        console.log('Occurance found in ' + index + ' position');
    }
    else if (index === -1 && i !== occurance) {
        console.log('Occurance not found in ' + occurance + ' position');
    }
    else {
        console.log('Occurance not found');
    }
}

yetAnotherGetNthOccurance(stringToMatch, 'ABC', 2);
// Output: Occurance found in 16 position

yetAnotherGetNthOccurance(stringToMatch, 'ABC', 20);
// Output: Occurance not found in 20 position

yetAnotherGetNthOccurance(stringToMatch, 'ZAB', 1)
// Output: Occurance not found

Solution 10 - Javascript

function getStringReminder(str, substr, occ) {
   let index = str.indexOf(substr);
   let preindex = '';
   let i = 1;
   while (index !== -1) {
      preIndex = index;
	  if (occ == i) {
		break;
	  }
      index = str.indexOf(substr, index + 1)
	  i++;
   }
   return preIndex;
}
console.log(getStringReminder('bcdefgbcdbcd', 'bcd', 3));

Solution 11 - Javascript

a simple solution just add string, character and idx:

function getCharIdx(str,char,n){
  let r = 0
  for (let i = 0; i<str.length; i++){
    if (str[i] === char){
      r++
      if (r === n){
        return i
      }

    }
   
  }
}

Solution 12 - Javascript

I needed a function that could search from the end of the string too so I wrote this:

function getPos(str, char, index, backwards) {
  var split = str.split(char);
  var result = 0;
  var done = false;

  split.forEach(function (item, i) {
    if (done) {return}
    result += item.length
    if (!backwards && i === index) {
      done = true
      return
    } else if (backwards && i === split.length - index - 2) {
      done = true
      return
    }  
    result += char.length
  })
  return result
}

Usage:

getPos('x x x', 'x', 1, false) // 2
getPos('x x x', 'x', 0, true) // 4

Solution 13 - Javascript

I was playing around with the following code for another question on StackOverflow and thought that it might be appropriate for here. The function printList2 allows the use of a regex and lists all the occurrences in order. (printList was an attempt at an earlier solution, but it failed in a number of cases.)

<html>
<head>
<title>Checking regex</title>
<script>
var string1 = "123xxx5yyy1234ABCxxxabc";
var search1 = /\d+/;
var search2 = /\d/;
var search3 = /abc/;
function printList(search) {
   document.writeln("<p>Searching using regex: " + search + " (printList)</p>");
   var list = string1.match(search);
   if (list == null) {
      document.writeln("<p>No matches</p>");
      return;
   }
   // document.writeln("<p>" + list.toString() + "</p>");
   // document.writeln("<p>" + typeof(list1) + "</p>");
   // document.writeln("<p>" + Array.isArray(list1) + "</p>");
   // document.writeln("<p>" + list1 + "</p>");
   var count = list.length;
   document.writeln("<ul>");
   for (i = 0; i < count; i++) {
      document.writeln("<li>" +  "  " + list[i] + "   length=" + list[i].length + 
          " first position=" + string1.indexOf(list[i]) + "</li>");
   }
   document.writeln("</ul>");
}
function printList2(search) {
   document.writeln("<p>Searching using regex: " + search + " (printList2)</p>");
   var index = 0;
   var partial = string1;
   document.writeln("<ol>");
   for (j = 0; j < 100; j++) {
       var found = partial.match(search);
       if (found == null) {
          // document.writeln("<p>not found</p>");
          break;
       }
       var size = found[0].length;
       var loc = partial.search(search);
       var actloc = loc + index;
       document.writeln("<li>" + found[0] + "  length=" + size + "  first position=" + actloc);
       // document.writeln("  " + partial + "  " + loc);
       partial = partial.substring(loc + size);
       index = index + loc + size;
       document.writeln("</li>");
   }
   document.writeln("</ol>");

}
</script>
</head>
<body>
<p>Original string is <script>document.writeln(string1);</script></p>
<script>
   printList(/\d+/g);
   printList2(/\d+/);
   printList(/\d/g);
   printList2(/\d/);
   printList(/abc/g);
   printList2(/abc/);
   printList(/ABC/gi);
   printList2(/ABC/i);
</script>
</body>
</html>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdam HalaszView Question on Stackoverflow
Solution 1 - JavascriptDenys SéguretView Answer on Stackoverflow
Solution 2 - JavascriptkennebecView Answer on Stackoverflow
Solution 3 - JavascriptilovettView Answer on Stackoverflow
Solution 4 - JavascriptFlorian MargaineView Answer on Stackoverflow
Solution 5 - JavascriptAlnitakView Answer on Stackoverflow
Solution 6 - JavascriptSharon ChoeView Answer on Stackoverflow
Solution 7 - JavascriptPiotrView Answer on Stackoverflow
Solution 8 - JavascriptEric AmshukovView Answer on Stackoverflow
Solution 9 - Javascriptsk8terboi87 ツView Answer on Stackoverflow
Solution 10 - JavascriptArul BenitoView Answer on Stackoverflow
Solution 11 - JavascriptCamille BasbousView Answer on Stackoverflow
Solution 12 - JavascriptT MackView Answer on Stackoverflow
Solution 13 - JavascriptBradley RossView Answer on Stackoverflow