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?
This question is related to
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;
}
}
}
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
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
}
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
}
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
}
}
}
}
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>_x000D_
<head>_x000D_
<title>Checking regex</title>_x000D_
<script>_x000D_
var string1 = "123xxx5yyy1234ABCxxxabc";_x000D_
var search1 = /\d+/;_x000D_
var search2 = /\d/;_x000D_
var search3 = /abc/;_x000D_
function printList(search) {_x000D_
document.writeln("<p>Searching using regex: " + search + " (printList)</p>");_x000D_
var list = string1.match(search);_x000D_
if (list == null) {_x000D_
document.writeln("<p>No matches</p>");_x000D_
return;_x000D_
}_x000D_
// document.writeln("<p>" + list.toString() + "</p>");_x000D_
// document.writeln("<p>" + typeof(list1) + "</p>");_x000D_
// document.writeln("<p>" + Array.isArray(list1) + "</p>");_x000D_
// document.writeln("<p>" + list1 + "</p>");_x000D_
var count = list.length;_x000D_
document.writeln("<ul>");_x000D_
for (i = 0; i < count; i++) {_x000D_
document.writeln("<li>" + " " + list[i] + " length=" + list[i].length + _x000D_
" first position=" + string1.indexOf(list[i]) + "</li>");_x000D_
}_x000D_
document.writeln("</ul>");_x000D_
}_x000D_
function printList2(search) {_x000D_
document.writeln("<p>Searching using regex: " + search + " (printList2)</p>");_x000D_
var index = 0;_x000D_
var partial = string1;_x000D_
document.writeln("<ol>");_x000D_
for (j = 0; j < 100; j++) {_x000D_
var found = partial.match(search);_x000D_
if (found == null) {_x000D_
// document.writeln("<p>not found</p>");_x000D_
break;_x000D_
}_x000D_
var size = found[0].length;_x000D_
var loc = partial.search(search);_x000D_
var actloc = loc + index;_x000D_
document.writeln("<li>" + found[0] + " length=" + size + " first position=" + actloc);_x000D_
// document.writeln(" " + partial + " " + loc);_x000D_
partial = partial.substring(loc + size);_x000D_
index = index + loc + size;_x000D_
document.writeln("</li>");_x000D_
}_x000D_
document.writeln("</ol>");_x000D_
_x000D_
}_x000D_
</script>_x000D_
</head>_x000D_
<body>_x000D_
<p>Original string is <script>document.writeln(string1);</script></p>_x000D_
<script>_x000D_
printList(/\d+/g);_x000D_
printList2(/\d+/);_x000D_
printList(/\d/g);_x000D_
printList2(/\d/);_x000D_
printList(/abc/g);_x000D_
printList2(/abc/);_x000D_
printList(/ABC/gi);_x000D_
printList2(/ABC/i);_x000D_
</script>_x000D_
</body>_x000D_
</html>
_x000D_
Using [String.indexOf][1]
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
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;
}
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));
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
*/
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);
};
Source: Stackoverflow.com